Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 6662


Ignore:
Timestamp:
Mar 31, 2010, 1:05:28 AM (14 years ago)
Author:
rgrieder
Message:

Merged revisions 6621-6661 to gamestates2.

Location:
code/branches/gamestates2
Files:
37 edited
2 copied

Legend:

Unmodified
Added
Removed
  • code/branches/gamestates2

  • code/branches/gamestates2/data/gui/scripts/AudioMenu.lua

    r6595 r6662  
    11-- AudioMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("AudioMenu")
    5 if _REQUIREDNAME == nil then
    6     AudioMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("AudioMenu")
    104
    11 function P:init()
     5function P.init()
    126    soundMgr = orxonox.SoundManager:getInstance()
    137    block = false
  • code/branches/gamestates2/data/gui/scripts/BasicGUI.lua

    r6595 r6662  
    1 -- gui.lua
     1-- BasicGUI.lua
    22
    33local P = {}
    4 if _REQUIREDNAME == nil then
    5     BasicGUI = P
    6 else
    7     _G[_REQUIREDNAME] = P
    8 end
     4_G[_REQUIREDNAME or "BasicGUI"] = P
    95
    106-- useless, even wrong? P is the class, not the object..
     
    2723end
    2824
    29 -- Override this function if you need to
     25-- Override this function if you want to change one of the three input parameters:
     26-- showCursor = true, useKeyboard = true and blockJoyStick = false
    3027-- But don't forget to stick to the naming convention ("GUI_" .. self.filename)
    3128function P:createInputState()
  • code/branches/gamestates2/data/gui/scripts/ControlsMenu.lua

    r6595 r6662  
    11-- ControlsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("ControlsMenu")
    5 if _REQUIREDNAME == nil then
    6     ControlsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("ControlsMenu")
    104
    115function P.ControlsMouseControlsButton_clicked(e)
  • code/branches/gamestates2/data/gui/scripts/CreditsMenu.lua

    r6595 r6662  
    11-- CreditsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("CreditsMenu")
    5 if _REQUIREDNAME == nil then
    6     CreditsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local sheetName = _REQUIREDNAME or "CreditsMenu"
     4-- Create object of type BasicGUI and make it global
     5local P = require("BasicGUI"):new(sheetName)
     6_G[sheetName] = P
    107
    118function P.CreditsBackButton_clicked(e)
  • code/branches/gamestates2/data/gui/scripts/DecisionPopup.lua

    r6595 r6662  
    11-- DecisionPopup.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("DecisionPopup")
    5 if _REQUIREDNAME == nil then
    6     DecisionPopup = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("DecisionPopup")
    104
    115function P.setCallback(functionPtr)
  • code/branches/gamestates2/data/gui/scripts/GUITools.lua

    r6417 r6662  
     1function createSheet(sheetName)
     2    -- Create object of type BasicGUI and make it global
     3    local sheet = require("BasicGUI"):new(sheetName)
     4    _G[sheetName] = sheet
     5    return sheet
     6end
     7
    18function openDecisionPopup( text, callbackPtr )
    29    showGUI("DecisionPopup", false, true)
  • code/branches/gamestates2/data/gui/scripts/GameplayMenu.lua

    r6595 r6662  
    11-- GameplayMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("GameplayMenu")
    5 if _REQUIREDNAME == nil then
    6     GameplayMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("GameplayMenu")
    104
    11 function P:init()
     5function P.init()
    126    dropdown = winMgr:getWindow("orxonox/ThemeCombobox")
    137    local themeList = {}
     
    2418function P.GameplayThemeCombobox_changed(e)
    2519    -- theme
    26     debug("event: theme")
     20    logMessage(0, "event: theme")
    2721end
    2822
    2923function P.GameplayDifficultyEasyButton_clicked(e)
    3024    -- difficulty easy
    31     debug("event: easy")
     25    logMessage(0, "event: easy")
    3226end
    3327
    3428function P.GameplayDifficultyNormalButton_clicked(e)
    3529    -- difficulty normal
    36     debug("event: normal")
     30    logMessage(0, "event: normal")
    3731end
    3832
    3933function P.GameplayDifficultyHardButton_clicked(e)
    4034    -- difficulty hard
    41     debug("event: hard")
     35    logMessage(0, "event: hard")
    4236end
    4337
  • code/branches/gamestates2/data/gui/scripts/GraphicsMenu.lua

    r6595 r6662  
    11-- GraphicsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("GraphicsMenu")
    5 if _REQUIREDNAME == nil then
    6     GraphicsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("GraphicsMenu")
    104
    11 function P:init()
     5function P.init()
    126    block = true
    137    file = orxonox.PathConfig:getConfigPathString() .. orxonox.getConfig("GraphicsManager", "ogreConfigFile_")
     
    149143    if scrollbar_active == false then
    150144        -- brightness
    151         debug("event: brightness")
     145        logMessage(0, "event: brightness")
    152146    end
    153147end
     
    159153function P.GraphicsBrightnessScrollbar_ended(e)
    160154    -- brightness
    161     debug("event: brightness")
     155    logMessage(0, "event: brightness")
    162156    scrollbar_active = false
    163157end
  • code/branches/gamestates2/data/gui/scripts/InGameMenu.lua

    r6595 r6662  
    11-- InGameMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("InGameMenu")
    5 if _REQUIREDNAME == nil then
    6     InGameMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("InGameMenu")
    104
    115-- events for ingamemenu
  • code/branches/gamestates2/data/gui/scripts/InfoPopup.lua

    r6595 r6662  
    11-- InfoPopup.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("InfoPopup")
    5 
    6 if _REQUIREDNAME == nil then
    7     InfoPopup = P
    8 else
    9     _G[_REQUIREDNAME] = P
    10 end
     3local P = createSheet("InfoPopup")
    114
    125function P.execute(functionPtr, arguments)
  • code/branches/gamestates2/data/gui/scripts/InitialiseGUI.lua

    r6595 r6662  
    2929system:setDefaultTooltip("MenuWidgets/Tooltip")
    3030
    31 loadedGUIs = {}
    32 cursorVisibility = {}
    33 activeSheets = {}
    34 nrOfActiveSheets = 0
    35 root = nil
    36 bShowsCursor = false
    37 bHidePrevious = {}
     31local loadedSheets = {}
     32local activeMenuSheets = {size = 0, topSheet = nil}
     33--activeHUDSheets  = {size = 0, topSheet = nil}
     34local root = nil
    3835
    3936-- Require all tools
    4037require("GUITools")
    4138
    42 -- loads the GUI with the specified filename
    43 -- be sure to set the global variable "filename" before calling this function
    44 function loadGUI(filename)
    45     -- check if it already exists
    46     loadedGui = loadedGUIs[filename]
    47     if loadedGui == nil then
    48         loadedGuiNS = require(filename)
    49         if loadedGuiNS == nil then
     39
     40-----------------------
     41--- Local functions ---
     42-----------------------
     43
     44-- Loads the GUI with the specified name
     45-- The name corresponds to the filename of the *.lua and *.layout files
     46-- but without the extension
     47local function loadSheet(name)
     48    -- Check if it has already been loaded
     49    local sheet = loadedSheets[name]
     50    if sheet == nil then
     51        -- Load the sheet
     52        sheet = require(name)
     53        if sheet == nil then
    5054            return
    5155        end
    52         loadedGui = loadedGuiNS:load()
    53         loadedGUIs[filename] = loadedGui
    54         -- if there has no GUI been loaded yet, set new GUI as current
    55         if table.getn(loadedGUIs) == 1 then
    56             current = loadedGUIs[1]
    57         end
    58         -- hide new GUI as we do not want to show it accidentially
    59         loadedGui:hide()
    60     end
    61     return loadedGui
    62 end
    63 
    64 function showGUI(filename, hidePrevious, bCursorVisible, ptr)
    65     gui = showGUI(filename, hidePrevious, bCursorVisible)
     56        sheet:load()
     57        loadedSheets[name] = sheet
     58        -- Hide new GUI as we do not want to show it accidentally
     59        sheet:hide()
     60    end
     61    return sheet
     62end
     63
     64local function hideCursor()
     65    if cursor:isVisible() then
     66        cursor:hide()
     67    end
     68end
     69
     70local function showCursor()
     71    if not cursor:isVisible() and orxonox.InputManager:getInstance():isMouseExclusive() then
     72        cursor:show()
     73    end
     74end
     75
     76local function find(table, value)
     77    for i, v in ipairs(table) do
     78        if v == value then
     79            return i
     80        end
     81    end
     82    return nil
     83end
     84
     85
     86------------------------
     87--- Global functions ---
     88------------------------
     89
     90-- ?
     91function showGUI(name, bHidePrevious, bShowCursor, ptr)
     92    gui = showGUI(name, bHidePrevious, bShowCursor)
    6693    gui.overlay = ptr
    6794end
    6895
    69 -- shows the specified GUI sheet and loads it if not loaded already
    70 function showGUI(filename, hidePrevious, bCursorVisible)
    71     if bCursorVisible == nil then
    72         if nrOfActiveSheets > 0 then
    73             bCursorVisible = cursorVisibility[activeSheets[nrOfActiveSheets]]
     96-- Shows the specified menu sheet and loads it if neccessary
     97function showGUI(name, bHidePrevious, bShowCursor)
     98    -- Handle default value for bShowCursor
     99    if bShowCursor == nil then
     100        if activeMenuSheets.size > 0 then
     101            bShowCursor = activeMenuSheets.topSheet.bShowCursor
    74102        else
    75             bCursorVisible = true
    76         end
    77     end
    78 
    79     if root == nil then
     103            bShowCursor = true
     104        end
     105    end
     106
     107    -- Hide if already displayed (to make sure it is up front in the end)
     108    if activeMenuSheets[name] ~= nil then
     109        hideGUI(name)
     110    end
     111
     112    if not root then
    80113        setBackground("")
    81114    end
    82115
    83     local currentGUI = loadedGUIs[filename]
    84     if(currentGUI == nil) then
    85         currentGUI = loadGUI(filename)
    86     end
    87 
    88     if(root:isChild(currentGUI.window)) then
    89         root:removeChildWindow(currentGUI.window)
    90     end
    91     root:addChildWindow(currentGUI.window)
    92 
    93     if bCursorVisible then
     116    -- Get sheet (or load it)
     117    local menuSheet = loadSheet(name)
     118    if not menuSheet then
     119        return
     120    end
     121
     122    -- Add sheet to the root window
     123    root:addChildWindow(menuSheet.window)
     124
     125    -- Pause game control if this is the first menu to be displayed
     126    -- HUGE HACK?
     127    if activeMenuSheets.size == 0 then
     128        orxonox.HumanController:pauseControl()
     129    end
     130
     131    -- Handle input distribution
     132    orxonox.InputManager:getInstance():enterState(menuSheet.inputState)
     133
     134    if bShowCursor then
    94135        showCursor()
    95136    else
     
    97138    end
    98139
    99     if find( activeSheets, filename ) ~= nil then
    100         table.remove( activeSheets, find( activeSheets, filename ) )
    101         nrOfActiveSheets = nrOfActiveSheets - 1
    102     else
    103         if nrOfActiveSheets == 0 then
    104             --orxonox.InputManager:getInstance():enterState("guiMouseOnly")
    105             orxonox.HumanController:pauseControl()
    106         end
    107     end
    108     orxonox.InputManager:getInstance():enterState(currentGUI.inputState)
    109 
    110     nrOfActiveSheets = nrOfActiveSheets + 1
    111     table.insert(activeSheets, filename)
    112     activeSheets[nrOfActiveSheets] = filename
    113     bHidePrevious[filename]=hidePrevious
    114     cursorVisibility[filename] = bCursorVisible
    115 
    116     if hidePrevious == true then
    117         for i=1,nrOfActiveSheets-1 do
    118             loadedGUIs[ activeSheets[i] ]:hide()
    119         end
    120     end
    121     currentGUI:show()
    122     return currentGUI
    123 end
    124 
    125 function hideCursor()
    126     if bShowsCursor==true then
    127         bShowsCursor=false
    128         cursor:hide()
    129     end
    130 end
    131 
    132 function showCursor()
    133     if bShowsCursor==false then
    134         bShowsCursor=true
    135         cursor:show()
    136     end
    137 end
    138 
    139 function hideGUI(filename)
    140     local currentGUI = loadedGUIs[filename]
    141     if currentGUI == nil then
     140    -- Add the sheet in a tuple of additional information
     141    local sheetTuple =
     142    {
     143        ["menuSheet"]      = menuSheet,
     144        ["name"]           = name,
     145        ["bShowCursor"]    = bShowCursor,
     146        ["bHidePrevious"]  = bHidePrevious
     147    }
     148    table.insert(activeMenuSheets, sheetTuple) -- indexed array access
     149    activeMenuSheets[name] = sheetTuple -- name access
     150    activeMenuSheets.size = activeMenuSheets.size + 1
     151    activeMenuSheets.topSheet = sheetTuple
     152
     153    -- Hide all previous sheets if necessary
     154    if bHidePrevious then
     155        for i = 1, activeMenuSheets.size - 1 do
     156            activeMenuSheets[i].menuSheet:hide()
     157        end
     158    end
     159
     160    menuSheet:show()
     161    return menuSheet
     162end
     163
     164function hideGUI(name)
     165    local sheetTuple = activeMenuSheets[name]
     166    if sheetTuple == nil then
    142167        return
    143168    end
    144     currentGUI:hide()
    145     if bHidePrevious[filename] == true then
    146         local i = nrOfActiveSheets-1
    147         while i>0 do
    148             loadedGUIs[ activeSheets[i] ]:show()
    149             if bHidePrevious[filename]==true then
    150                 break
    151             else
    152                 i=i-1
     169
     170    -- Hide the sheet
     171    sheetTuple.menuSheet:hide()
     172
     173    -- Show sheets that were hidden by the sheet to be removed
     174    local i = activeMenuSheets.size
     175    -- Only do something if all sheets on top of sheetTuple
     176    -- have bHidePrevious == false and sheetTuple.bHidePrevious == true
     177    while i > 0 do
     178        if activeMenuSheets[i].bHidePrevious == true then
     179            if activeMenuSheets[i] == sheetTuple then
     180                i = i - 1
     181                while i > 0 do
     182                    activeMenuSheets[i].menuSheet:show()
     183                    if activeMenuSheets[i].bHidePrevious == true then
     184                        break
     185                    end
     186                    i = i - 1
     187                end
    153188            end
    154         end
    155     end
    156     root:removeChildWindow(currentGUI.window)
    157     local i=1
    158     while activeSheets[i] do
    159         if activeSheets[i+1] == nil then
    160             if activeSheets[i-1] ~= nil then
    161                 if cursorVisibility[ activeSheets[i-1] ] == true then
    162                     showCursor()
    163                 else
    164                     hideCursor()
    165                 end
    166             else
    167                 hideCursor()
    168             end
    169         end
    170         if activeSheets[i] == filename then
    171             table.remove( activeSheets, i )
    172             nrOfActiveSheets = nrOfActiveSheets-1
    173         else
    174             i = i+1
    175         end
    176     end
    177     cursorVisibility[filename] = nil -- remove the cursor visibility of the current gui from the table
    178     bHidePrevious[filename] = nil
    179     if nrOfActiveSheets == 0 then
    180         --orxonox.InputManager:getInstance():leaveState("guiMouseOnly")
     189            break
     190        end
     191        i = i - 1
     192    end
     193
     194    -- Remove sheet with its tuple from the table
     195    root:removeChildWindow(sheetTuple.menuSheet.window)
     196    table.remove(activeMenuSheets, find(activeMenuSheets, sheetTuple))
     197    activeMenuSheets[name] = nil
     198    activeMenuSheets.size = activeMenuSheets.size - 1
     199    activeMenuSheets.topSheet = activeMenuSheets[activeMenuSheets.size]
     200
     201    -- Leave the input state
     202    orxonox.InputManager:getInstance():leaveState(sheetTuple.menuSheet.inputState)
     203   
     204    -- See whether to show or hide cursor
     205    if activeMenuSheets.size > 0 and activeMenuSheets.topSheet.bShowCursor then
     206        showCursor()
     207    else
     208        hideCursor()
     209    end
     210
     211    -- Resume control if the last menu is hidden
     212    if activeMenuSheets.size == 0 then
    181213        orxonox.HumanController:resumeControl()
    182214        hideCursor()
    183215    end
    184     orxonox.InputManager:getInstance():leaveState(currentGUI.inputState)
    185 end
    186 
     216end
     217
     218-- Hides all menu GUI sheets
    187219function hideAllGUIs()
    188     while nrOfActiveSheets ~= 0 do
    189         hideGUI(activeSheets[nrOfActiveSheets])
     220    while activeMenuSheets.size ~= 0 do
     221        hideGUI(activeMenuSheets.topSheet.name)
    190222    end
    191223end
    192224
    193225function keyESC()
    194     if nrOfActiveSheets == 1 and activeSheets[1] == "MainMenu" then
     226    -- HUGE, very HUGE hacks!
     227    if activeMenuSheets.size == 1 and activeMenuSheets[1].name == "MainMenu" then
    195228        orxonox.execute("exit")
    196     elseif nrOfActiveSheets > 0 then
    197         orxonox.execute("hideGUI "..activeSheets[nrOfActiveSheets])
     229    elseif activeMenuSheets.size > 0 then
     230        orxonox.execute("hideGUI "..activeMenuSheets.topSheet.name)
    198231    else
    199232        showGUI("InGameMenu")
     
    201234end
    202235
    203 function setBackground(filename)
     236function setBackground(name)
    204237    local newroot
    205238    if root ~= nil then
    206239        root:rename("oldRootWindow")
    207240    end
    208     if filename ~= "" then
    209         newroot = winMgr:loadWindowLayout(filename .. ".layout")
     241    if name ~= "" then
     242        newroot = winMgr:loadWindowLayout(name .. ".layout")
    210243        newroot:rename("AbsoluteRootWindow")
    211244        system:setGUISheet(newroot)
     
    228261    root = newroot
    229262end
    230 
    231 function find(table, value)
    232     local i=0
    233     while table[i] ~= nil do
    234         if table[i]==value then
    235             return i
    236         else
    237             i=i+1
    238         end
    239     end
    240     return nil
    241 end
    242 
    243 function test(e)
    244     debug(0, "Blubb")
    245 end
  • code/branches/gamestates2/data/gui/scripts/KeyBindMenu.lua

    r6595 r6662  
    11-- KeyBindMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("KeyBindMenu")
    5 
    6 if _REQUIREDNAME == nil then
    7     KeyBindMenu = P
    8 else
    9     _G[_REQUIREDNAME] = P
    10 end
    11 
    12 function P:init()
     3local P = createSheet("KeyBindMenu")
     4
     5function P.init()
    136
    147    commandList = {}
  • code/branches/gamestates2/data/gui/scripts/MainMenu.lua

    r6595 r6662  
    11-- MainMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("MainMenu")
    5 if _REQUIREDNAME == nil then
    6     MainMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("MainMenu")
    104
    115-- events for MainMenu
  • code/branches/gamestates2/data/gui/scripts/MouseControlsMenu.lua

    r6595 r6662  
    11-- MouseControlsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("MouseControlsMenu")
    5 if _REQUIREDNAME == nil then
    6     MouseControlsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("MouseControlsMenu")
    104
    11 function P:init()
     5function P.init()
    126    block = false
    137    mousenormalscrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/MouseNormalScrollbar"),"CEGUI::Scrollbar")
  • code/branches/gamestates2/data/gui/scripts/MultiplayerMenu.lua

    r6595 r6662  
    11-- MultiplayerMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("MultiplayerMenu")
    5 if _REQUIREDNAME == nil then
    6     MultiplayerMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("MultiplayerMenu")
    104
    11 function P:init()
     5function P.init()
    126    listbox = winMgr:getWindow("orxonox/MultiplayerLevelListbox")
    137    preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
  • code/branches/gamestates2/data/gui/scripts/MultiplayerOptionsMenu.lua

    r6595 r6662  
    11-- MultiplayerOptionsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("MultiplayerOptionsMenu")
    5 if _REQUIREDNAME == nil then
    6     MultiplayerOptionsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("MultiplayerOptionsMenu")
    104
    115function P.MultiplayerOptionsBackButton_clicked(e)
  • code/branches/gamestates2/data/gui/scripts/PickupInventory.lua

    r6595 r6662  
    11-- PickupInventory.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("PickupInventory")
    5 if _REQUIREDNAME == nil then
    6     PickupInventory = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("PickupInventory")
    104
    115P.lastEquipmentCount_ = 0
     
    148
    159-- events
    16 function P:frmUpdate(e)
     10function P.frmUpdate(e)
    1711    local equipCount = orxonox.PickupInventory:getEquipmentCount()
    1812    local usableCount = orxonox.PickupInventory:getUsableCount()
    1913
    20     if equipCount ~= self.lastEquipmentCount_ or usableCount ~= self.lastUsableCount_ then
    21         self:updateTabs()
     14    if equipCount ~= P.lastEquipmentCount_ or usableCount ~= P.lastUsableCount_ then
     15        P.updateTabs()
    2216    end
    2317end
     
    3125end
    3226
    33 function P:mItemClicked(e)
     27function P.mItemClicked(e)
    3428    local w = CEGUI.toWindowEventArgs(e).window
    3529    local name = w:getName()
     
    4236
    4337    if t == "use" then
    44         if self.currentUsableID_ >= 0 then
    45             winMgr:getWindow("orxonox/Inventory/Title/use/" .. self.currentUsableID_):setProperty("TextColours", "tl:FFFFFFFF tr:FFFFFFFF bl:FFFFFFFF br:FFFFFFFF")
     38        if P.currentUsableID_ >= 0 then
     39            winMgr:getWindow("orxonox/Inventory/Title/use/" .. P.currentUsableID_):setProperty("TextColours", "tl:FFFFFFFF tr:FFFFFFFF bl:FFFFFFFF br:FFFFFFFF")
    4640        end
    4741        orxonox.PickupInventory:selectUsable(tonumber(i))
    48         self.currentUsableID_ = tonumber(i)
     42        P.currentUsableID_ = tonumber(i)
    4943        winMgr:getWindow("orxonox/Inventory/Title/use/" .. i):setProperty("TextColours", "tl:FFFF4444 tr:FFFF4444 bl:FFFF4444 br:FFFF4444")
    5044    end
     
    5246
    5347-- methods
    54 function P:updateTabs()
     48function P.updateTabs()
    5549    local eqWin = winMgr:getWindow("orxonox/Inventory/TabControl/TabEquipment")
    5650    local usWin = winMgr:getWindow("orxonox/Inventory/TabControl/TabUsable")
     
    5852    orxonox.PickupInventory:getSingleton():updateTabs(winMgr, eqWin, usWin)
    5953
    60     self.currentUsableID_ = orxonox.PickupInventory:getCurrentUsableIndex()
    61     self.lastEquipmentCount_ = orxonox.PickupInventory:getEquipmentCount()
    62     self.lastUsableCount_ = orxonox.PickupInventory:getUsableCount()
     54    P.currentUsableID_ = orxonox.PickupInventory:getCurrentUsableIndex()
     55    P.lastEquipmentCount_ = orxonox.PickupInventory:getEquipmentCount()
     56    P.lastUsableCount_ = orxonox.PickupInventory:getUsableCount()
    6357end
    6458
  • code/branches/gamestates2/data/gui/scripts/QuestGUI.lua

    r6595 r6662  
    1 gui = require("BasicGUI")
    2 local P = BasicGUI:new("QuestGUI")
    3 if _REQUIREDNAME == nil then
    4     QuestGUI = P
    5 else
    6     _G[_REQUIREDNAME] = P
    7 end
     1-- QuestGUI.lua
    82
    9 function P:show()
    10     self.window:show() -- TDO: Do this through parent...
    11     self.visible = true
     3local P = createSheet("QuestGUI")
     4
     5function P.show()
     6    P.window:show() -- TDO: Do this through parent...
     7    P.visible = true
    128
    139    local questManager = orxonox.QuestManager:getInstance()
  • code/branches/gamestates2/data/gui/scripts/SettingsMenu.lua

    r6595 r6662  
    11-- SettingsMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("SettingsMenu")
    5 if _REQUIREDNAME == nil then
    6     SettingsMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("SettingsMenu")
    104
    115function P.SettingsGameplayButton_clicked(e)
     
    3125function P.SettingsResetSettingsButton_clicked(e)
    3226    -- reset settings
    33     debug("event: reset settings")
     27    logMessage(0, "event: reset settings")
    3428end
    3529
  • code/branches/gamestates2/data/gui/scripts/SingleplayerMenu.lua

    r6595 r6662  
    11-- SingleplayerMenu.lua
    22
    3 BasicGUI = require("BasicGUI")
    4 local P = BasicGUI:new("SingleplayerMenu")
    5 if _REQUIREDNAME == nil then
    6     SingleplayerMenu = P
    7 else
    8     _G[_REQUIREDNAME] = P
    9 end
     3local P = createSheet("SingleplayerMenu")
    104
    11 function P:init()
     5function P.init()
    126    listbox = winMgr:getWindow("orxonox/SingleplayerLevelListbox")
    137    preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
  • code/branches/gamestates2/data/lua/LuaStateInit.lua

    r6536 r6662  
    11-- Note: luaState is a pointer to the LuaState instance that created this lua state
    22
    3 -- Save original print function in debug
    4 debug = print
    5 
    63-- Redirect print to the C++ print function
     4original_print = print
    75print = function(s)
    86  luaState:luaPrint(s)
     
    1311  luaState:luaLog(level, message)
    1412end
     13cout = logMessage
    1514
    1615-- Redirect dofile in order to load with the resource manager
    17 doFile = function(filename)
     16original_dofile = dofile
     17dofile = function(filename)
    1818  luaState:doFile(filename)
    19   -- Required because the C++ function cannot return whatever might be on the stack
     19  -- Required because if the file returns a table, it cannot be passed through the C++ function
    2020  return LuaStateReturnValue -- C-injected global variable
    2121end
    22 original_dofile = dofile
    23 dofile = doFile
     22doFile = dofile
    2423
    2524-- Create includeFile function that preparses the file according
     
    2726include = function(filename)
    2827  luaState:includeFile(filename)
    29   -- Required because the C++ function cannot return whatever might be on the stack
     28  -- Required because if the file returns a table, it cannot be passed through the C++ function
    3029  return LuaStateReturnValue -- C-injected global variable
    3130end
     
    3433-- The loaded modules are then stored with their names (where name has no .lua extension)
    3534-- Furthermore the ".lua" extension is appended to the moduleName parameter when looking for the file
    36 old_require = require
     35original_require = require
     36_REQUIREDNAME = ""
     37LuaStateReturnValue = true
    3738require = function(moduleName)
    3839  if not luaState:fileExists(moduleName .. ".lua") then
     40    logMessage(2, "Warning: Lua function require() could not find file '" .. moduleName .. ".lua' ")
    3941    return nil
    4042  end
     
    4244    _LOADED = {}
    4345  end
    44   if not _LOADED[moduleName] then
     46  if _LOADED[moduleName] == nil then
    4547    -- save old value
    46     _REQUIREDNAME_OLD = _REQUIREDNAME
     48    local _REQUIREDNAME_OLD = _REQUIREDNAME
    4749    _REQUIREDNAME = moduleName
    4850    luaState:doFile(moduleName .. ".lua")
    49     _LOADED[moduleName] = LuaStateReturnValue or true
     51    -- LuaStateReturnValue is required because if the file returns a table,
     52    -- it cannot be passed through the C++ function
     53    if LuaStateReturnValue == nil then -- C-injected global variable
     54        LuaStateReturnValue = true
     55    end
     56    _LOADED[moduleName] = LuaStateReturnValue -- This entry must never be nil
    5057    -- restore old value
    5158    _REQUIREDNAME = _REQUIREDNAME_OLD
     
    5360  return _LOADED[moduleName]
    5461end
     62
     63
     64-- Include command line debugger for lua 5.1
     65-- Note: It doesn't work if the IOConsole was started. Then we replace pause() with a warning
     66if _VERSION ~= "Lua 5.0"  and not luaState:usingIOConsole() then
     67  require("Debugger")
     68else
     69  -- Fallback pause function
     70  pause = function()
     71    logMessage(2, [["Warning: debug() called in Lua, but Debugger is not active.
     72Do you have the IOConsole disabled and are you using Lua version 5.1?"]])
     73  end
     74end
     75
     76-- General error handler that gets called whenever an error happens at runtime
     77errorHandler = function(err)
     78  -- Display the error message
     79  if type(err) == "string" then
     80    logMessage(1, "Lua runtime error: "..err)
     81  end
     82
     83  -- Start debugger if possible
     84  if _LOADED and _LOADED["Debugger"] ~= nil then
     85    pause()
     86  else
     87    -- Fallback: print stack trace
     88    logMessage(1, debug.traceback(2))
     89  end
     90  return err -- Hello Lua debugger user! Please type 'set 2' to get to the
     91             -- actual position in the stack where the error occurred
     92end
     93
    5594
    5695-- Convenience function for console commands
  • code/branches/gamestates2/src/libraries/core/Core.cc

    r6595 r6662  
    7878
    7979    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
     80    SetCommandLineSwitch(noIOConsole).information("Use this if you don't want to use the IOConsole (for instance for Lua debugging)");
    8081#ifdef ORXONOX_PLATFORM_WINDOWS
    8182    SetCommandLineArgument(limitToCPU, 1).information("Limits the program to one CPU/core (1, 2, 3, etc.). Default is the first core (faster than off)");
     
    8889        , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands)
    8990        , bGraphicsLoaded_(false)
     91        , bStartIOConsole_(true)
    9092    {
    9193        // Set the hard coded fixed paths
     
    149151
    150152        // create persistent io console
    151         this->ioConsole_.reset(new IOConsole());
     153        if (CommandLineParser::getValue("noIOConsole").getBool())
     154        {
     155            ModifyConfigValue(bStartIOConsole_, tset, false);
     156        }
     157        if (this->bStartIOConsole_)
     158            this->ioConsole_.reset(new IOConsole());
    152159
    153160        // creates the class hierarchy for all classes with factories
     
    193200            .description("If true, all random actions are different each time you start the game")
    194201            .callback(this, &Core::initRandomNumberGenerator);
     202        SetConfigValue(bStartIOConsole_, true)
     203            .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)");
    195204    }
    196205
     
    327336        }
    328337        // Process console events and status line
    329         this->ioConsole_->preUpdate(time);
     338        if (this->ioConsole_ != NULL)
     339            this->ioConsole_->preUpdate(time);
    330340        // Process thread commands
    331341        this->tclThreadManager_->preUpdate(time);
  • code/branches/gamestates2/src/libraries/core/Core.h

    r6595 r6662  
    9797            scoped_ptr<TclBind>           tclBind_;
    9898            scoped_ptr<TclThreadManager>  tclThreadManager_;
    99             scoped_ptr<Scope<ScopeID::Root> >     rootScope_;
     99            scoped_ptr<Scope<ScopeID::Root> > rootScope_;
    100100            // graphical
    101101            scoped_ptr<GraphicsManager>   graphicsManager_;     //!< Interface to OGRE
     
    108108            std::string                   language_;                   //!< The language
    109109            bool                          bInitRandomNumberGenerator_; //!< If true, srand(time(0)) is called
     110            bool                          bStartIOConsole_;            //!< Set to false if you don't want to use the IOConsole
    110111
    111112            static Core*                  singletonPtr_s;
  • code/branches/gamestates2/src/libraries/core/GUIManager.cc

    r6595 r6662  
    253253    }
    254254
    255     const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showMouse, TriBool::Value useKeyboard, bool bBlockJoyStick)
     255    const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick)
    256256    {
    257257        InputState* state = InputManager::getInstance().createInputState(name);
    258258
    259         if (GraphicsManager::getInstance().isFullScreen() && showMouse == TriBool::True ||
    260            !GraphicsManager::getInstance().isFullScreen() && showMouse == TriBool::False)
     259        /* Table that maps isFullScreen() and showCursor to mouseExclusive
     260        isFullscreen / showCursor | True  | False | Dontcare
     261        ----------------------------------------------------
     262        true                      | True  | True  | Dontcare
     263        ----------------------------------------------------
     264        false                     | False | True  | Dontcare
     265        */
     266        if (showCursor == TriBool::Dontcare)
     267            state->setMouseExclusive(TriBool::Dontcare);
     268        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False)
    261269            state->setMouseExclusive(TriBool::True);
    262270        else
    263             state->setMouseExclusive(TriBool::Dontcare);
    264 
    265         if (showMouse == TriBool::True)
     271            state->setMouseExclusive(TriBool::False);
     272
     273        if (showCursor == TriBool::True)
    266274            state->setMouseHandler(this);
    267         else if (showMouse == TriBool::False)
     275        else if (showCursor == TriBool::False)
    268276            state->setMouseHandler(&InputHandler::EMPTY);
    269277
  • code/branches/gamestates2/src/libraries/core/GUIManager.h

    r6595 r6662  
    8181        void setBackground(const std::string& name);
    8282
    83         const std::string& createInputState(const std::string& name, TriBool::Value showMouse = TriBool::True, TriBool::Value useKeyboard = TriBool::True, bool bBlockJoyStick = false); // tolua_export
     83        const std::string& createInputState(const std::string& name, TriBool::Value showCursor = TriBool::True, TriBool::Value useKeyboard = TriBool::True, bool bBlockJoyStick = false); // tolua_export
    8484
    8585        void setCamera(Ogre::Camera* camera);
  • code/branches/gamestates2/src/libraries/core/LuaState.cc

    r6417 r6662  
    3737
    3838#include "util/Debug.h"
     39#include "util/Exception.h"
     40#include "util/ScopeGuard.h"
     41#include "IOConsole.h"
    3942#include "Resource.h"
    4043#include "ToluaBindCore.h"
     
    5457        // Create new lua state and configure it
    5558        luaState_ = lua_open();
     59        Loki::ScopeGuard luaStateGuard = Loki::MakeGuard(&lua_close, luaState_);
    5660#if LUA_VERSION_NUM == 501
    5761        luaL_openlibs(luaState_);
     
    7882
    7983        // Parse init script
    80         this->doFile("LuaStateInit.lua");
     84        if (!this->doFile("LuaStateInit.lua"))
     85            ThrowException(InitialisationFailed, "Running LuaStateInit.lua failed");
     86
     87        luaStateGuard.Dismiss();
    8188    }
    8289
     
    96103    }
    97104
    98     void LuaState::includeFile(const std::string& filename)
     105    bool LuaState::includeFile(const std::string& filename)
    99106    {
    100107        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
    101108        if (sourceInfo != NULL)
    102             this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
    103         else
    104             COUT(2) << "LuaState: Cannot include file '" << filename << "'." << std::endl;
    105     }
    106 
    107     void LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     109            return this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
     110        else
     111        {
     112            COUT(2) << "LuaState: Cannot include file '" << filename << "' (not found)." << std::endl;
     113            return false;
     114        }
     115    }
     116
     117    bool LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
    108118    {
    109119        // Parse string with provided include parser (otherwise don't preparse at all)
     
    114124            luaInput = code;
    115125
    116         this->doString(luaInput, sourceFileInfo);
    117     }
    118 
    119     void LuaState::doFile(const std::string& filename)
     126        if (sourceFileInfo != NULL)
     127        {
     128            // Also fill a map with the actual source code. This is just for the include* commands
     129            // where the content of sourceFileInfo->filename doesn't match 'code'
     130            this->sourceCodeMap_[sourceFileInfo->filename] = code;
     131        }
     132
     133        bool returnValue = this->doString(luaInput, sourceFileInfo);
     134
     135        if (sourceFileInfo != NULL)
     136        {
     137            // Delete source code entry
     138            if (sourceFileInfo != NULL)
     139                this->sourceCodeMap_.erase(sourceFileInfo->filename);
     140        }
     141
     142        return returnValue;
     143    }
     144
     145    bool LuaState::doFile(const std::string& filename)
    120146    {
    121147        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
    122148        if (sourceInfo != NULL)
    123             this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
    124         else
    125             COUT(2) << "LuaState: Cannot do file '" << filename << "'." << std::endl;
    126     }
    127 
    128     void LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     149            return this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
     150        else
     151        {
     152            COUT(2) << "LuaState: Cannot do file '" << filename << "' (not found)." << std::endl;
     153            return false;
     154        }
     155    }
     156
     157    bool LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
    129158    {
    130159        // Save the old source file info
     
    134163            sourceFileInfo_ = sourceFileInfo;
    135164
    136         int error = 0;
     165        std::string chunkname;
     166        if (sourceFileInfo != NULL)
     167        {
     168            // Provide lua_load with the filename for debug purposes
     169            // The '@' is a Lua convention to identify the chunk name as filename
     170            chunkname = '@' + sourceFileInfo->filename;
     171        }
     172        else
     173        {
     174            // Use the code string to identify the chunk
     175            chunkname = code;
     176        }
     177
     178        // Push custom error handler that uses the debugger
     179        int errorHandler = 1;
     180        lua_getglobal(this->luaState_, "errorHandler");
     181        if (lua_isnil(this->luaState_, -1))
     182        {
     183            lua_pop(this->luaState_, 1);
     184            errorHandler = 0;
     185        }
     186
    137187#if LUA_VERSION_NUM != 501
    138188        LoadS ls;
    139189        ls.s = code.c_str();
    140190        ls.size = code.size();
    141         error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
     191        int error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, chunkname.c_str());
    142192#else
    143         error = luaL_loadstring(luaState_, code.c_str());
     193        int error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.c_str());
    144194#endif
    145195
    146         // execute the chunk
     196        switch (error)
     197        {
     198        case LUA_ERRSYNTAX: // Syntax error
     199            COUT(1) << "Lua syntax error: " << lua_tostring(luaState_, -1) << std::endl;
     200            break;
     201        case LUA_ERRMEM:    // Memory allocation error
     202            COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
     203            lua_pop(luaState_, 1);
     204            break;
     205        }
     206
    147207        if (error == 0)
    148             error = lua_pcall(luaState_, 0, 1, 0);
     208        {
     209            // Execute the chunk in protected mode with an error handler function (stack index)
     210            error = lua_pcall(luaState_, 0, 1, errorHandler);
     211
     212            switch (error)
     213            {
     214            case LUA_ERRRUN: // Runtime error
     215                // Remove error string from stack (we already display the error in the
     216                // 'errorHandler' Lua function in LuaStateInit.lua)
     217                lua_pop(luaState_, 1);
     218                break;
     219            case LUA_ERRERR: // Error in the error handler
     220                COUT(1) << "Lua error in error handler: " << lua_tostring(luaState_, -1) << std::endl;
     221                break;
     222            case LUA_ERRMEM: // Memory allocation error
     223                COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
     224                lua_pop(luaState_, 1);
     225                break;
     226            }
     227        }
     228
    149229        if (error != 0)
    150230        {
    151             std::string origin;
    152             if (sourceFileInfo != NULL)
    153                 origin = " originating from " + sourceFileInfo_->filename;
    154             COUT(1) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
    155             // return value is nil
     231            // Push a nil return value
    156232            lua_pushnil(luaState_);
    157233        }
    158         // push return value because it will get lost since the return value of this function is void
     234
     235        // Set return value to a global variable because we cannot return a table in this function
     236        // here. It would work for numbers, pointers and strings, but certainly not for Lua tables.
    159237        lua_setglobal(luaState_, "LuaStateReturnValue");
    160238
    161239        // Load the old info again
    162240        sourceFileInfo_ = oldSourceFileInfo;
     241
     242        return (error == 0);
    163243    }
    164244
     
    180260        else
    181261            return true;
     262    }
     263
     264    //! Returns the content of a file
     265    std::string LuaState::getSourceCode(const std::string& filename)
     266    {
     267        // Try the internal map first to get the actual Lua code
     268        // and not just some pseudo Lua-XML code when using include* commands
     269        std::map<std::string, std::string>::const_iterator it = this->sourceCodeMap_.find(filename);
     270        if (it != this->sourceCodeMap_.end())
     271            return it->second;
     272        shared_ptr<ResourceInfo> info = Resource::getInfo(filename);
     273        if (info == NULL)
     274            return "";
     275        else
     276            return Resource::open(info)->getAsString();
     277    }
     278
     279    bool LuaState::usingIOConsole() const
     280    {
     281        return IOConsole::exists();
    182282    }
    183283
  • code/branches/gamestates2/src/libraries/core/LuaState.h

    r6595 r6662  
    7171        ~LuaState();
    7272
    73         void doFile(const std::string& filename); // tolua_export
    74         void doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
     73        bool doFile(const std::string& filename); // tolua_export
     74        bool doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
    7575
    76         void includeFile(const std::string& filename); // tolua_export
    77         void includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
     76        bool includeFile(const std::string& filename); // tolua_export
     77        bool includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
    7878
    7979        void luaPrint(const std::string& str); // tolua_export
    8080        void luaLog(unsigned int level, const std::string& message); // tolua_export
    8181        bool fileExists(const std::string& filename); // tolua_export
     82        std::string getSourceCode(const std::string& filename); // tolua_export
    8283
    8384        const std::stringstream& getOutput() const { return output_; }
     
    9192
    9293        Functor* createLuaFunctor(const std::string& code) { return new LuaFunctor(code, this); } // tolua_export
     94        //! Tells about whether IOConsole was activated. The Lua debugger only works with a normal console.
     95        bool usingIOConsole() const; // tolua_export
    9396
    9497        static bool addToluaInterface(int (*function)(lua_State*), const std::string& name);
     
    114117        bool bIsRunning_;
    115118        shared_ptr<ResourceInfo> sourceFileInfo_;
     119        std::map<std::string, std::string> sourceCodeMap_;
    116120        std::string (*includeParseFunction_)(const std::string&);
    117121
  • code/branches/gamestates2/src/libraries/core/Resource.cc

    r6501 r6662  
    2929#include "Resource.h"
    3030
     31#include <boost/filesystem/path.hpp>
    3132#include <OgreException.h>
     33#include <OgreFileSystem.h>
    3234#include <OgreResourceGroupManager.h>
    3335
     
    8991                ptr->group = group;
    9092                ptr->size = it->uncompressedSize;
     93                if (dynamic_cast<Ogre::FileSystemArchive*>(it->archive) != NULL)
     94                {
     95                    boost::filesystem::path base(it->archive->getName());
     96                    base /= it->filename;
     97                    ptr->fileSystemPath = base.string();
     98                }
    9199                return ptr;
    92100            }
  • code/branches/gamestates2/src/libraries/core/Resource.h

    r6417 r6662  
    5757        //! Uncompressed size
    5858        size_t size;
     59        //! Absolute file path ("" for files not on filesystem)
     60        std::string fileSystemPath;
    5961    };
    6062
  • code/branches/gamestates2/src/libraries/core/input/InputDevice.h

    r6417 r6662  
    159159            for (unsigned int iB = 0; iB < pressedButtons_.size(); ++iB)
    160160                for (unsigned int iS = 0; iS < inputStates_.size(); ++iS)
    161                     inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits>(
     161                    inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits::ButtonTypeParam>(
    162162                        this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(pressedButtons_[iB]));
    163163
     
    196196            // Call states
    197197            for (unsigned int i = 0; i < inputStates_.size(); ++i)
    198                 inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
     198                inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
    199199        }
    200200
     
    218218            // Call states
    219219            for (unsigned int i = 0; i < inputStates_.size(); ++i)
    220                 inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
     220                inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
    221221        }
    222222
  • code/branches/gamestates2/src/libraries/core/input/InputHandler.h

    r6105 r6662  
    112112        virtual ~InputHandler() { }
    113113
    114         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::TPress)
     114        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TPress)
    115115            { this->buttonPressed(button); }
    116         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::TRelease)
     116        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TRelease)
    117117            { this->buttonReleased(button); }
    118         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::THold)
     118        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::THold)
    119119            { this->buttonHeld(button); }
    120         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
     120        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
    121121            { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); }
    122         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
     122        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
    123123            { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); }
    124         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
     124        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
    125125            { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); }
    126126
  • code/branches/gamestates2/src/libraries/core/input/InputManager.cc

    r6595 r6662  
    9595        CCOUT(4) << "Constructing..." << std::endl;
    9696
     97        // Allocate space for the function call buffer
     98        this->callBuffer_.reserve(16);
     99
    97100        this->setConfigValues();
    98101
     
    266269        CCOUT(3) << "Destroying..." << std::endl;
    267270
     271        // Leave all active InputStates (except "empty")
     272        while (this->activeStates_.size() > 1)
     273            this->leaveState(this->activeStates_.rbegin()->second->getName());
     274        this->activeStates_.clear();
     275
    268276        // Destroy calibrator helper handler and state
    269277        this->destroyState("calibrator");
    270278        // Destroy KeyDetector and state
    271279        calibratorCallbackHandler_->destroy();
    272         // destroy the empty InputState
     280        // Destroy the empty InputState
    273281        this->destroyStateInternal(this->emptyState_);
    274282
    275         // destroy all user InputStates
     283        // Destroy all user InputStates
    276284        while (statesByName_.size() > 0)
    277285            this->destroyStateInternal(statesByName_.rbegin()->second);
     
    335343    void InputManager::reload()
    336344    {
    337         if (internalState_ & Ticking)
    338         {
    339             // We cannot destroy OIS right now, because reload was probably
    340             // caused by a user clicking on a GUI item. The stack trace would then
    341             // include an OIS method. So it would be a very bad thing to destroy it..
    342             internalState_ |= ReloadRequest;
    343         }
    344         else if (internalState_ & Calibrating)
     345        if (internalState_ & Calibrating)
    345346            CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl;
    346347        else
     
    351352    void InputManager::reloadInternal()
    352353    {
    353         CCOUT(3) << "Reloading ..." << std::endl;
     354        CCOUT(4) << "Reloading ..." << std::endl;
    354355
    355356        this->destroyDevices();
     
    357358
    358359        internalState_ &= ~Bad;
    359         internalState_ &= ~ReloadRequest;
    360360        CCOUT(4) << "Reloading complete." << std::endl;
    361361    }
     
    370370        if (internalState_ & Bad)
    371371            ThrowException(General, "InputManager was not correctly reloaded.");
    372 
    373         else if (internalState_ & ReloadRequest)
    374             reloadInternal();
    375 
    376         // check for states to leave
    377         if (!stateLeaveRequests_.empty())
    378         {
    379             for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
    380                 it != stateLeaveRequests_.end(); ++it)
    381             {
    382                 (*it)->left();
    383                 // just to be sure that the state actually is registered
    384                 assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    385 
    386                 activeStates_.erase((*it)->getPriority());
    387                 if ((*it)->getPriority() < InputStatePriority::HighPriority)
    388                     (*it)->setPriority(0);
    389                 updateActiveStates();
    390             }
    391             stateLeaveRequests_.clear();
    392         }
    393 
    394         // check for states to enter
    395         if (!stateEnterRequests_.empty())
    396         {
    397             for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
    398                 it != stateEnterRequests_.end(); ++it)
    399             {
    400                 // just to be sure that the state actually is registered
    401                 assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    402 
    403                 if ((*it)->getPriority() == 0)
    404                 {
    405                     // Get smallest possible priority between 1 and maxStateStackSize_s
    406                     for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
    407                         rit != activeStates_.rend(); ++rit)
    408                     {
    409                         if (rit->first < InputStatePriority::HighPriority)
    410                         {
    411                             (*it)->setPriority(rit->first + 1);
    412                             break;
    413                         }
    414                     }
    415                     // In case no normal handler was on the stack
    416                     if ((*it)->getPriority() == 0)
    417                         (*it)->setPriority(1);
    418                 }
    419                 activeStates_[(*it)->getPriority()] = (*it);
    420                 updateActiveStates();
    421                 (*it)->entered();
    422             }
    423             stateEnterRequests_.clear();
    424         }
    425 
    426         // check for states to destroy
    427         if (!stateDestroyRequests_.empty())
    428         {
    429             for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
    430                 it != stateDestroyRequests_.end(); ++it)
    431             {
    432                 destroyStateInternal((*it));
    433             }
    434             stateDestroyRequests_.clear();
    435         }
    436372
    437373        // check whether a state has changed its EMPTY situation
     
    448384            updateActiveStates();
    449385
    450         // mark that we now start capturing and distributing input
    451         internalState_ |= Ticking;
    452 
    453         // Capture all the input and handle it
     386        // Capture all the input and collect the function calls
     387        // No event gets triggered here yet!
    454388        BOOST_FOREACH(InputDevice* device, devices_)
    455389            if (device != NULL)
    456390                device->update(time);
    457391
    458         // Update the states
     392        // Collect functions calls for the update
    459393        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
    460394            activeStatesTicked_[i]->update(time.getDeltaTime());
    461395
    462         internalState_ &= ~Ticking;
     396        // Execute all cached function calls in order
     397        // Why so complicated? The problem is that an InputHandler could trigger
     398        // a reload that would destroy the OIS devices or it could even leave and
     399        // then destroy its own InputState. That would of course lead to access
     400        // violations.
     401        // If we delay the calls, then OIS and and the InputStates are not anymore
     402        // in the call stack and can therefore be edited.
     403        for (size_t i = 0; i < this->callBuffer_.size(); ++i)
     404            this->callBuffer_[i]();
     405
     406        this->callBuffer_.clear();
    463407    }
    464408
     
    470414    void InputManager::updateActiveStates()
    471415    {
    472         assert((internalState_ & InputManager::Ticking) == 0);
    473416        // temporary resize
    474417        for (unsigned int i = 0; i < devices_.size(); ++i)
     
    622565        // get pointer from the map with all stored handlers
    623566        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
    624         if (it != statesByName_.end())
    625         {
    626             // exists
    627             if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
    628             {
    629                 // not active
    630                 if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
     567        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
     568        {
     569            // exists and not active
     570            if (it->second->getPriority() == 0)
     571            {
     572                // Get smallest possible priority between 1 and maxStateStackSize_s
     573                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
     574                    rit != activeStates_.rend(); ++rit)
    631575                {
    632                     // not scheduled for destruction
    633                     // prevents a state from being added multiple times
    634                     stateEnterRequests_.insert(it->second);
    635                     return true;
     576                    if (rit->first < InputStatePriority::HighPriority)
     577                    {
     578                        it->second->setPriority(rit->first + 1);
     579                        break;
     580                    }
    636581                }
    637             }
    638             else if (this->stateLeaveRequests_.find(it->second) != this->stateLeaveRequests_.end())
    639             {
    640                 // State already scheduled for leaving --> cancel
    641                 this->stateLeaveRequests_.erase(this->stateLeaveRequests_.find(it->second));
    642             }
     582                // In case no normal handler was on the stack
     583                if (it->second->getPriority() == 0)
     584                    it->second->setPriority(1);
     585            }
     586            activeStates_[it->second->getPriority()] = it->second;
     587            updateActiveStates();
     588            it->second->entered();
     589
     590            return true;
    643591        }
    644592        return false;
     
    654602        // get pointer from the map with all stored handlers
    655603        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
    656         if (it != statesByName_.end())
    657         {
    658             // exists
    659             if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
    660             {
    661                 // active
    662                 stateLeaveRequests_.insert(it->second);
    663                 return true;
    664             }
    665             else if (this->stateEnterRequests_.find(it->second) != this->stateEnterRequests_.end())
    666             {
    667                 // State already scheduled for entering --> cancel
    668                 this->stateEnterRequests_.erase(this->stateEnterRequests_.find(it->second));
    669             }
     604        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
     605        {
     606            // exists and active
     607
     608            it->second->left();
     609
     610            activeStates_.erase(it->second->getPriority());
     611            if (it->second->getPriority() < InputStatePriority::HighPriority)
     612                it->second->setPriority(0);
     613            updateActiveStates();
     614
     615            return true;
    670616        }
    671617        return false;
     
    682628        if (it != statesByName_.end())
    683629        {
    684             if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
    685             {
    686                 // The state is still active. We have to postpone
    687                 stateLeaveRequests_.insert(it->second);
    688                 stateDestroyRequests_.insert(it->second);
    689             }
    690             else if (this->internalState_ & Ticking)
    691             {
    692                 // cannot remove state while ticking
    693                 stateDestroyRequests_.insert(it->second);
    694             }
    695             else
    696                 destroyStateInternal(it->second);
     630            this->leaveState(name);
     631            destroyStateInternal(it->second);
    697632
    698633            return true;
     
    704639    void InputManager::destroyStateInternal(InputState* state)
    705640    {
    706         assert(state && !(this->internalState_ & Ticking));
    707         std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
    708         if (it != this->activeStates_.end())
    709         {
    710             this->activeStates_.erase(it);
    711             updateActiveStates();
    712         }
     641        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
    713642        statesByName_.erase(state->getName());
    714643        state->destroy();
  • code/branches/gamestates2/src/libraries/core/input/InputManager.h

    r6595 r6662  
    3636#include <string>
    3737#include <vector>
     38#include <boost/function.hpp>
    3839
    3940#include "util/Singleton.h"
    4041#include "util/TriBool.h"
    4142#include "core/WindowEventListener.h"
    42 #include "InputState.h"
    4343
    4444// tolua_begin
     
    7676            Nothing       = 0x00,
    7777            Bad           = 0x02,
    78             Ticking       = 0x04,
    79             Calibrating   = 0x08,
    80             ReloadRequest = 0x10,
     78            Calibrating   = 0x04,
    8179        };
    8280
     
    170168        //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing!
    171169        OIS::InputManager* getOISInputManager() { return this->oisInputManager_; }
     170        //! Returns the position of the cursor as std::pair of ints
    172171        std::pair<int, int> getMousePosition() const;
     172        //! Tells whether the mouse is used exclusively to the game
     173        bool isMouseExclusive() const { return this->exclusiveMouse_; } // tolua_export
     174
     175        //-------------------------------
     176        // Function call caching
     177        //-------------------------------
     178        void pushCall(const boost::function<void ()>& function)
     179            { this->callBuffer_.push_back(function); }
    173180
    174181        static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export
     
    208215        std::vector<InputState*>            activeStatesTicked_;   //!< Like activeStates_, but only contains the ones that currently receive events
    209216
    210         std::set<InputState*>               stateEnterRequests_;   //!< Requests to enter a new state
    211         std::set<InputState*>               stateLeaveRequests_;   //!< Requests to leave a running state
    212         std::set<InputState*>               stateDestroyRequests_; //!< Requests to destroy a state
     217        std::vector<boost::function<void ()> > callBuffer_;        //!< Caches all calls from InputStates to be executed afterwards (see preUpdate)
    213218
    214219        static InputManager*                singletonPtr_s;        //!< Pointer reference to the singleton
  • code/branches/gamestates2/src/libraries/core/input/InputPrereqs.h

    r6417 r6662  
    4242#include <ois/OISMouse.h>
    4343#include <ois/OISJoyStick.h>
     44#include "util/OrxEnum.h"
    4445
    4546namespace orxonox
     
    448449        };
    449450    }
     451
     452    //! Enumeration wrapper for input state priorities
     453    struct InputStatePriority : OrxEnum<InputStatePriority>
     454    {
     455        OrxEnumConstructors(InputStatePriority);
     456
     457        static const int Empty        = -1;
     458        static const int Dynamic      = 0;
     459
     460        static const int HighPriority = 1000;
     461        static const int Console      = HighPriority + 0;
     462        static const int Calibrator   = HighPriority + 1;
     463        static const int Detector     = HighPriority + 2;
     464    };
    450465}
    451466
  • code/branches/gamestates2/src/libraries/core/input/InputState.h

    r6595 r6662  
    3535#include <string>
    3636#include <vector>
    37 
    38 #include "util/OrxEnum.h"
     37#include <boost/function.hpp>
     38#include <boost/bind.hpp>
     39
    3940#include "util/TriBool.h"
    4041#include "InputHandler.h"
     42#include "InputManager.h"
    4143#include "JoyStickQuantityListener.h"
     44
     45#define INPUT_STATE_PUSH_CALL(deviceIndex, functionName, ...) \
     46    InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(&InputHandler::functionName, handlers_[deviceIndex], __VA_ARGS__)))
    4247
    4348namespace orxonox
    4449{
    45     //! Enumeration wrapper for input state priorities
    46     struct InputStatePriority : OrxEnum<InputStatePriority>
    47     {
    48         OrxEnumConstructors(InputStatePriority);
    49 
    50         static const int Empty        = -1;
    51         static const int Dynamic      = 0;
    52 
    53         static const int HighPriority = 1000;
    54         static const int Console      = HighPriority + 0;
    55         static const int Calibrator   = HighPriority + 1;
    56         static const int Detector     = HighPriority + 2;
    57     };
    58 
    59 
    6050    /**
    6151    @brief
     
    144134
    145135        //! Generic function that distributes all 9 button events
    146         template <typename EventType, class Traits>
    147         void buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button);
     136        template <typename EventType, class ButtonTypeParam>
     137        void buttonEvent(unsigned int device, ButtonTypeParam button);
    148138
    149139        //! Event handler
     
    190180        for (unsigned int i = 0; i < handlers_.size(); ++i)
    191181            if (handlers_[i] != NULL)
    192                 handlers_[i]->allDevicesUpdated(dt);
     182                INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt);
    193183    }
    194184
     
    199189        case InputDeviceEnumerator::Keyboard:
    200190            if (handlers_[keyboardIndex_s] != NULL)
    201                 handlers_[keyboardIndex_s]->keyboardUpdated(dt);
     191                INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt);
    202192            break;
    203193
    204194        case InputDeviceEnumerator::Mouse:
    205195            if (handlers_[mouseIndex_s] != NULL)
    206                 handlers_[mouseIndex_s]->mouseUpdated(dt);
     196                INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt);
    207197            break;
    208198
    209199        default: // joy sticks
    210200            if (handlers_[device] != NULL)
    211                 handlers_[device]->joyStickUpdated(device - firstJoyStickIndex_s, dt);
     201                INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt);
    212202            break;
    213203        }
    214204    }
    215205
    216     template <typename EventType, class Traits>
    217     FORCEINLINE void InputState::buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button)
     206    template <typename EventType, class ButtonTypeParam>
     207    FORCEINLINE void InputState::buttonEvent(unsigned int device, typename ButtonTypeParam button)
    218208    {
    219209        assert(device < handlers_.size());
    220210        if (handlers_[device] != NULL)
    221             handlers_[device]->buttonEvent(device, button, EventType());
     211        {
     212            // We have to store the function pointer to tell the compiler about its actual type because of overloading
     213            void (InputHandler::*function)(unsigned int, ButtonTypeParam, EventType) = &InputHandler::buttonEvent<ButtonTypeParam>;
     214            InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(function, handlers_[device], device, button, EventType())));
     215        }
    222216    }
    223217
     
    225219    {
    226220        if (handlers_[mouseIndex_s] != NULL)
    227             handlers_[mouseIndex_s]->mouseMoved(abs, rel, clippingSize);
     221            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize);
    228222    }
    229223
     
    231225    {
    232226        if (handlers_[mouseIndex_s] != NULL)
    233             handlers_[mouseIndex_s]->mouseScrolled(abs, rel);
     227            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel);
    234228    }
    235229
     
    238232        assert(device < handlers_.size());
    239233        if (handlers_[device] != NULL)
    240             handlers_[device]->axisMoved(device - firstJoyStickIndex_s, axis, value);
     234            INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value);
    241235    }
    242236}
  • code/branches/gamestates2/src/libraries/util/Singleton.h

    r6536 r6662  
    4949    public:
    5050        //! Returns a reference to the singleton instance
    51         static T& getInstance()
     51        FORCEINLINE static T& getInstance()
    5252        {
    5353            assert(T::singletonPtr_s != NULL);
     
    5656
    5757        //! Tells whether the singleton has been created
    58         static bool exists()
     58        FORCEINLINE static bool exists()
    5959        {
    6060            return (T::singletonPtr_s != NULL);
     
    6262
    6363        //! Update method called by ClassSingletonManager (if used)
    64         void preUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->preUpdate(time); }
     64        FORCEINLINE void preUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->preUpdate(time); }
    6565        //! Empty update method for the static polymorphism
    66         void preUpdate(const Clock& time) { }
     66        FORCEINLINE void preUpdate(const Clock& time) { }
    6767        //! Update method called by ClassSingletonManager (if used)
    68         void postUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->postUpdate(time); }
     68        FORCEINLINE void postUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->postUpdate(time); }
    6969        //! Empty update method for the static polymorphism
    70         void postUpdate(const Clock& time) { }
     70        FORCEINLINE void postUpdate(const Clock& time) { }
    7171
    7272    protected:
Note: See TracChangeset for help on using the changeset viewer.