diff --git a/addons/.gitignore b/addons/.gitignore new file mode 100644 index 00000000..1d77474f --- /dev/null +++ b/addons/.gitignore @@ -0,0 +1,3 @@ +* +!/README.txt +!.gitignore diff --git a/addons/README.txt b/addons/README.txt new file mode 100644 index 00000000..136500ff --- /dev/null +++ b/addons/README.txt @@ -0,0 +1 @@ +You can plance any personal addons here. diff --git a/modules/client/client.otmod b/modules/client/client.otmod deleted file mode 100644 index 7b1c65c6..00000000 --- a/modules/client/client.otmod +++ /dev/null @@ -1,24 +0,0 @@ -Module - name: client - description: Load all other otclient dependecies - author: OTClient team - website: https://github.com/edubart/otclient - canUnload: false - - // NOTE: order does matter - dependencies: - - client_background - - client_topmenu - - client_tibiafiles - - client_about - - client_options - - client_entergame - - client_modulemanager - - game - - onLoad: | - dofile 'client' - Client.init() - - onUnload: | - Client.terminate() diff --git a/modules/client_about/about.otmod b/modules/client_about/about.otmod index 4bc7a306..898f15ae 100644 --- a/modules/client_about/about.otmod +++ b/modules/client_about/about.otmod @@ -3,6 +3,12 @@ Module description: Create the about window author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 160 + unloadable: true + + dependencies: + - client_topmenu onLoad: | dofile 'about' diff --git a/modules/client_background/background.otmod b/modules/client_background/background.otmod index 16af71db..ddf8d386 100644 --- a/modules/client_background/background.otmod +++ b/modules/client_background/background.otmod @@ -3,6 +3,8 @@ Module description: Handles the background of the login screen author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 110 onLoad: | dofile 'background' diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index 10b22dc1..52d56332 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -42,11 +42,11 @@ local function tryLogin(charInfo, tries) Game.loginWorld(EnterGame.account, EnterGame.password, charInfo.worldHost, charInfo.worldPort, charInfo.characterName) loadBox = displayCancelBox('Please wait', 'Connecting to game server...') - function loadBox.onCancel() - loadBox = nil - Game.cancelLogin() - CharacterList.show() - end + connect(loadBox, { onCancel = function() + loadBox = nil + Game.cancelLogin() + CharacterList.show() + end }) -- save last used character Settings.set('lastUsedCharacter', charInfo.characterName) diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 19cda80b..df66c35f 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -8,7 +8,6 @@ local motdMessage local motdButton local enterGameButton - -- private functions local function clearAccountFields() enterGame:getChildById('accountNameLineEdit'):clearText() @@ -20,11 +19,13 @@ end local function onError(protocol, message, connectionError) loadBox:destroy() + loadBox = nil + if not connectionError then clearAccountFields() end local errorBox = displayErrorBox('Login Error', message) - errorBox.onOk = EnterGame.show + connect(errorBox, { onOk = EnterGame.show }) end local function onMotd(protocol, motd) @@ -43,13 +44,15 @@ local function onCharacterList(protocol, characters, premDays) end loadBox:destroy() + loadBox = nil + CharacterList.create(characters, premDays) local lastMotdNumber = Settings.getNumber("motd") if motdNumber and motdNumber ~= lastMotdNumber then Settings.set("motd", motdNumber) local motdBox = displayInfoBox("Message of the day", motdMessage) - motdBox.onOk = CharacterList.show + connect(motdBox, { onOk = CharacterList.show }) CharacterList.hide() end end @@ -76,8 +79,13 @@ function EnterGame.init() enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0) enterGame:getChildById('accountNameLineEdit'):focus() - if #account > 0 and autologin then - addEvent(EnterGame.doLogin) + -- only open entergame when app starts + if not g_app.isRunning() then + if #account > 0 and autologin then + addEvent(EnterGame.doLogin) + end + else + enterGame:hide() end end @@ -124,10 +132,11 @@ function EnterGame.doLogin() protocolLogin.onCharacterList = onCharacterList loadBox = displayCancelBox('Please wait', 'Connecting to login server...') - loadBox.onCancel = function(msgbox) - protocolLogin:cancelLogin() - EnterGame.show() - end + connect(loadBox, { onCancel = function(msgbox) + loadBox = nil + protocolLogin:cancelLogin() + EnterGame.show() + end }) protocolLogin:login(EnterGame.host, EnterGame.port, EnterGame.account, EnterGame.password) end diff --git a/modules/client_entergame/entergame.otmod b/modules/client_entergame/entergame.otmod index 6f96379d..9da96cde 100644 --- a/modules/client_entergame/entergame.otmod +++ b/modules/client_entergame/entergame.otmod @@ -3,6 +3,8 @@ Module description: Manages enter game and character list windows author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 150 onLoad: | dofile 'entergame' diff --git a/modules/client/client.lua b/modules/client_main/client.lua similarity index 98% rename from modules/client/client.lua rename to modules/client_main/client.lua index 05d1db73..60f1450f 100644 --- a/modules/client/client.lua +++ b/modules/client_main/client.lua @@ -34,5 +34,4 @@ function Client.terminate() Settings.set('window-size', g_window.getUnmaximizedSize()) Settings.set('window-pos', g_window.getUnmaximizedPos()) Settings.set('window-maximized', g_window.isMaximized()) - g_window.hide() end diff --git a/modules/client_main/client.otmod b/modules/client_main/client.otmod new file mode 100644 index 00000000..f968137b --- /dev/null +++ b/modules/client_main/client.otmod @@ -0,0 +1,14 @@ +Module + name: client_main + description: Initialize the client and setups its main window + author: OTClient team + website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 100 + + onLoad: | + dofile 'client' + Client.init() + + onUnload: | + Client.terminate() diff --git a/modules/client/clienticon.png b/modules/client_main/clienticon.png similarity index 100% rename from modules/client/clienticon.png rename to modules/client_main/clienticon.png diff --git a/modules/client_modulemanager/modulemanager.lua b/modules/client_modulemanager/modulemanager.lua index a0071d45..b13e7be1 100644 --- a/modules/client_modulemanager/modulemanager.lua +++ b/modules/client_modulemanager/modulemanager.lua @@ -54,25 +54,40 @@ function ModuleManager.refreshModules() end function ModuleManager.listModules() + if not moduleManagerWindow then return end + moduleList:destroyChildren() local modules = g_modules.getModules() for i,module in ipairs(modules) do local label = createWidget('ModuleListLabel', moduleList) label:setText(module:getName()) + label:setOn(module:isLoaded()) end moduleList:focusChild(moduleList:getFirstChild(), ActiveFocusReason) end +function ModuleManager.refreshLoadedModules() + if not moduleManagerWindow then return end + + for i,child in ipairs(moduleList:getChildren()) do + local module = g_modules.getModule(child:getText()) + child:setOn(module:isLoaded()) + end +end + function ModuleManager.updateModuleInfo(moduleName) + if not moduleManagerWindow then return end + local name = '' local description = '' local autoLoad = '' local author = '' local website = '' local version = '' - local canLoad = false + local loaded = false + local canReload = false local canUnload = false local module = g_modules.getModule(moduleName) @@ -82,8 +97,9 @@ function ModuleManager.updateModuleInfo(moduleName) author = module:getAuthor() website = module:getWebsite() version = module:getVersion() - canUnload = module:isLoaded() - canLoad = not canUnload + loaded = module:isLoaded() + canUnload = module:canUnload() + canReload = not loaded or canUnload end moduleManagerWindow:recursiveGetChildById('moduleName'):setText(name) @@ -93,17 +109,26 @@ function ModuleManager.updateModuleInfo(moduleName) moduleManagerWindow:recursiveGetChildById('moduleWebsite'):setText(website) moduleManagerWindow:recursiveGetChildById('moduleVersion'):setText(version) - moduleManagerWindow:recursiveGetChildById('moduleLoadButton'):setEnabled(canLoad) - moduleManagerWindow:recursiveGetChildById('moduleUnloadButton'):setEnabled(canUnload) + local reloadButton = moduleManagerWindow:recursiveGetChildById('moduleReloadButton') + reloadButton:setEnabled(canReload) + reloadButton:setVisible(true) + if loaded then reloadButton:setText('Reload') + else reloadButton:setText('Load') end + + local unloadButton = moduleManagerWindow:recursiveGetChildById('moduleUnloadButton') + unloadButton:setVisible(true) + unloadButton:setEnabled(canUnload) end -function ModuleManager.loadCurrentModule() +function ModuleManager.reloadCurrentModule() local focusedChild = moduleList:getFocusedChild() if focusedChild then local module = g_modules.getModule(focusedChild:getText()) if module then - module:load() + module:reload() ModuleManager.updateModuleInfo(module:getName()) + ModuleManager.refreshLoadedModules() + ModuleManager.show() end end end @@ -115,7 +140,14 @@ function ModuleManager.unloadCurrentModule() if module then module:unload() ModuleManager.updateModuleInfo(module:getName()) + ModuleManager.refreshLoadedModules() end end end +function ModuleManager.reloadAllModules() + g_modules.reloadModules() + ModuleManager.refreshLoadedModules() + ModuleManager.show() +end + diff --git a/modules/client_modulemanager/modulemanager.otmod b/modules/client_modulemanager/modulemanager.otmod index 9fee752e..c66210b0 100644 --- a/modules/client_modulemanager/modulemanager.otmod +++ b/modules/client_modulemanager/modulemanager.otmod @@ -3,6 +3,12 @@ Module description: Manage other modules author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 140 + + dependencies: + - client_topmenu + onLoad: | dofile 'modulemanager' ModuleManager.init() diff --git a/modules/client_modulemanager/modulemanager.otui b/modules/client_modulemanager/modulemanager.otui index a41cba75..69bb012b 100644 --- a/modules/client_modulemanager/modulemanager.otui +++ b/modules/client_modulemanager/modulemanager.otui @@ -3,11 +3,21 @@ ModuleListLabel < Label background-color: alpha text-offset: 2 0 focusable: true + color: #cccccc $focus: - background-color: #ffffff22 color: #ffffff + $on: + background-color: #006600 + $!on: + background-color: #660000 + + $on focus: + background-color: #004400 + $!on focus: + background-color: #440000 + ModuleInfoLabel < Label $!first: margin-top: 5 @@ -19,10 +29,11 @@ ModuleValueLabel < UILabel text-offset: 3 0 image-source: /core_styles/images/panel_flat.png image-border: 1 + height: 16 MainWindow id: moduleManagerWindow - size: 450 450 + size: 480 450 text: Module Manager @onEscape: ModuleManager.hide() @@ -38,21 +49,31 @@ MainWindow margin-bottom: 30 Button + id: refreshModulesButton anchors.top: moduleList.bottom - anchors.horizontalCenter: moduleList.horizontalCenter + anchors.left: moduleList.left margin-top: 8 + width: 80 text: Refresh @onClick: ModuleManager.refreshModules() + Button + id: reloadAllModulesButton + anchors.top: moduleList.bottom + anchors.right: moduleList.right + margin-top: 8 + width: 80 + text: Reload All + @onClick: ModuleManager.reloadAllModules() + Panel id: moduleInfo anchors.left: moduleList.right anchors.top: parent.top anchors.right: parent.right margin: 0 5 5 15 - layout: - type: verticalBox - fit-children: true + layout: verticalBox + height: 265 ModuleInfoLabel text: Module name @@ -65,11 +86,6 @@ MainWindow id: moduleDescription height: 100 - ModuleInfoLabel - text: Loaded - ModuleValueLabel - id: moduleLoaded - //ModuleInfoLabel // text: Autoload //ModuleValueLabel @@ -97,13 +113,13 @@ MainWindow id: moduleVersion Button - id: moduleLoadButton + id: moduleReloadButton anchors.top: moduleInfo.bottom anchors.left: moduleInfo.left margin-top: 8 text: Load - enabled: false - @onClick: ModuleManager.loadCurrentModule() + visible: false + @onClick: ModuleManager.reloadCurrentModule() Button id: moduleUnloadButton @@ -112,6 +128,6 @@ MainWindow margin-left: 10 margin-top: 8 text: Unload - enabled: false + visible: false @onClick: ModuleManager.unloadCurrentModule() diff --git a/modules/client_options/options.otmod b/modules/client_options/options.otmod index 714f93e5..1ceda63e 100644 --- a/modules/client_options/options.otmod +++ b/modules/client_options/options.otmod @@ -3,6 +3,11 @@ Module description: Create the options window author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 130 + + dependencies: + - client_topmenu onLoad: | dofile 'options' diff --git a/modules/addon_terminal/commands.lua b/modules/client_terminal/commands.lua similarity index 89% rename from modules/addon_terminal/commands.lua rename to modules/client_terminal/commands.lua index 36dd70ff..45403a51 100644 --- a/modules/addon_terminal/commands.lua +++ b/modules/client_terminal/commands.lua @@ -45,14 +45,6 @@ function quit() exit() end -function reloadModule(name) - local module = g_modules.getModule(name) - if module then - module:unload() - module:load() - end -end - function autoReloadModule(name) local function reloadEvent() reloadModule(name) diff --git a/modules/addon_terminal/terminal.lua b/modules/client_terminal/terminal.lua similarity index 98% rename from modules/addon_terminal/terminal.lua rename to modules/client_terminal/terminal.lua index 14601b26..9b405f88 100644 --- a/modules/addon_terminal/terminal.lua +++ b/modules/client_terminal/terminal.lua @@ -86,7 +86,10 @@ end local function doCommand() local currentCommand = commandLineEdit:getText() Terminal.executeCommand(currentCommand) - commandLineEdit:clearText() + + if commandLineEdit then + commandLineEdit:clearText() + end return true end diff --git a/modules/addon_terminal/terminal.otmod b/modules/client_terminal/terminal.otmod similarity index 78% rename from modules/addon_terminal/terminal.otmod rename to modules/client_terminal/terminal.otmod index d03ccfe3..7cc5618f 100644 --- a/modules/addon_terminal/terminal.otmod +++ b/modules/client_terminal/terminal.otmod @@ -1,11 +1,10 @@ Module - name: terminal + name: client_terminal description: Terminal for executing lua functions author: OTClient team website: https://github.com/edubart/otclient - - autoLoad: true - autoLoadAntecedence: 200 + autoload: true + autoload-antecedence: 160 onLoad: | dofile 'terminal' diff --git a/modules/addon_terminal/terminal.otui b/modules/client_terminal/terminal.otui similarity index 100% rename from modules/addon_terminal/terminal.otui rename to modules/client_terminal/terminal.otui diff --git a/modules/addon_terminal/terminal.png b/modules/client_terminal/terminal.png similarity index 100% rename from modules/addon_terminal/terminal.png rename to modules/client_terminal/terminal.png diff --git a/modules/client_topmenu/topmenu.lua b/modules/client_topmenu/topmenu.lua index ce81d020..22bd8e0f 100644 --- a/modules/client_topmenu/topmenu.lua +++ b/modules/client_topmenu/topmenu.lua @@ -24,6 +24,9 @@ function TopMenu.init() TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout) Keyboard.bindKeyDown('Ctrl+Q', onLogout) + + connect(Game, { onLogin = TopMenu.showGameButtons, + onLogout = TopMenu.hideGameButtons }) end function TopMenu.terminate() @@ -33,6 +36,9 @@ function TopMenu.terminate() gameButtonsPanel = nil topMenu:destroy() topMenu = nil + + disconnect(Game, { onLogin = TopMenu.showGameButtons, + onLogout = TopMenu.hideGameButtons }) end function TopMenu.addButton(id, description, icon, callback, right) @@ -82,6 +88,3 @@ end function TopMenu.getButton(id) return topMenu:recursiveGetChildById(id) end - -connect(Game, { onLogin = TopMenu.showGameButtons, - onLogout = TopMenu.hideGameButtons }) diff --git a/modules/client_topmenu/topmenu.otmod b/modules/client_topmenu/topmenu.otmod index f2cfe727..a2ff5ef7 100644 --- a/modules/client_topmenu/topmenu.otmod +++ b/modules/client_topmenu/topmenu.otmod @@ -3,6 +3,8 @@ Module description: Create the top menu author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 120 onLoad: | dofile 'topmenu' diff --git a/modules/core/core.otmod b/modules/core/core.otmod deleted file mode 100644 index a8dcefa9..00000000 --- a/modules/core/core.otmod +++ /dev/null @@ -1,17 +0,0 @@ -Module - name: core - description: Contains lua classes, functions and constants used by other modules - author: OTClient team - website: https://github.com/edubart/otclient - - // core must be loaded before other modules - autoLoad: true - autoLoadAntecedence: 10 - - // NOTE: order does matter - dependencies: - - core_lib - - core_fonts - - core_styles - - core_widgets - diff --git a/modules/core_fonts/core_fonts.otmod b/modules/core_fonts/core_fonts.otmod index 51e68b2c..1dcc0c5c 100644 --- a/modules/core_fonts/core_fonts.otmod +++ b/modules/core_fonts/core_fonts.otmod @@ -3,7 +3,8 @@ Module description: Contains fonts used by core author: OTClient team website: https://github.com/edubart/otclient - canUnload: false + autoload: true + autoload-antecedence: 30 onLoad: | importFont 'verdana-11px-antialised' diff --git a/modules/core_lib/core_lib.otmod b/modules/core_lib/core_lib.otmod index 763fba02..1039eba8 100644 --- a/modules/core_lib/core_lib.otmod +++ b/modules/core_lib/core_lib.otmod @@ -3,6 +3,8 @@ Module description: Contains core lua classes, functions and constants used by other modules author: OTClient team website: https://github.com/edubart/otclient + autoload: true + autoload-antecedence: 10 onLoad: | dofile 'ext/table' @@ -21,5 +23,3 @@ Module dofile 'keyboard' dofile 'mouse' - onUnload: | - rootWidget = nil diff --git a/modules/core_lib/dispatcher.lua b/modules/core_lib/dispatcher.lua index 0f323c74..8c9f12e5 100644 --- a/modules/core_lib/dispatcher.lua +++ b/modules/core_lib/dispatcher.lua @@ -1,34 +1,20 @@ -local eventId = 0 -local eventList = {} - function scheduleEvent(func, delay) - if not func then return end - eventId = eventId + 1 - local id = eventId - local function proxyFunc() - if eventList[id] then - if eventList[id].active then - func() - end - eventList[id] = nil - end - end - eventList[id] = { func = proxyFunc, active = true } - if delay and delay > 0 then - g_dispatcher.scheduleEvent(proxyFunc, delay) - else - g_dispatcher.addEvent(proxyFunc, false) - end - return id + local event = g_dispatcher.scheduleEvent(callback, delay) + + -- must hold a reference to the callback, otherwise it would be collected + event._callback = callback + return event end -function addEvent(func) - return scheduleEvent(func, 0) +function addEvent(callback, front) + local event = g_dispatcher.addEvent(callback, front) + -- must hold a reference to the callback, otherwise it would be collected + event._callback = callback + return event end -function removeEvent(id) - if id and eventList[id] then - eventList[id].active = false - return true +function removeEvent(event) + if event then + event:cancel() end end diff --git a/modules/core_lib/globals.lua b/modules/core_lib/globals.lua index 65a58911..f74bf79c 100644 --- a/modules/core_lib/globals.lua +++ b/modules/core_lib/globals.lua @@ -74,3 +74,16 @@ function createWidget(style, parent) widget:setStyle(style) return widget end + +function reloadModule(name) + local module = g_modules.getModule(name) + if module then + module:reload() + end +end + +function reloadModules() + g_modules.reloadModules() +end + + diff --git a/modules/core_lib/util.lua b/modules/core_lib/util.lua index 0fad2e46..d0bc1292 100644 --- a/modules/core_lib/util.lua +++ b/modules/core_lib/util.lua @@ -35,6 +35,28 @@ function connect(object, signalsAndSlots, pushFront) end end +function disconnect(object, signalsAndSlots) + for signal,slot in pairs(signalsAndSlots) do + if not object[signal] then + elseif type(object[signal]) == 'function' then + if object[signal] == slot then + object[signal] = nil + end + elseif type(object[signal]) == 'table' then + for k,func in pairs(object[signal]) do + if func == slot then + table.remove(object[signal], k) + + if #object[signal] == 1 then + object[signal] = object[signal][1] + end + break + end + end + end + end +end + function extends(base) local derived = {} function derived.internalCreate() diff --git a/modules/core_styles/core_styles.otmod b/modules/core_styles/core_styles.otmod index 6858dec0..dad82a32 100644 --- a/modules/core_styles/core_styles.otmod +++ b/modules/core_styles/core_styles.otmod @@ -3,6 +3,9 @@ Module description: Contains ui styles used by other modules author: OTClient team website: https://github.com/edubart/otclient + reloadable: true + autoload: true + autoload-antecedence: 20 onLoad: | importStyle 'styles/buttons.otui' @@ -20,3 +23,4 @@ Module importStyle 'styles/popupmenus.otui' importStyle 'styles/comboboxes.otui' importStyle 'styles/spinboxes.otui' + importStyle 'styles/messagebox.otui' diff --git a/modules/core_styles/styles/messagebox.otui b/modules/core_styles/styles/messagebox.otui new file mode 100644 index 00000000..a9922054 --- /dev/null +++ b/modules/core_styles/styles/messagebox.otui @@ -0,0 +1,19 @@ +MessageBoxWindow < MainWindow + id: messageBoxWindow + anchors.centerIn: parent + height: 60 + width: 80 + padding-bottom: 10 + padding-right: 10 + +MessageBoxLabel < Label + id: messageBoxLabel + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + +MessageBoxRightButton < Button + id: messageBoxRightButton + anchors.bottom: parent.bottom + anchors.right: parent.right + width: 64 + visible: true diff --git a/modules/core_styles/styles/windows.otui b/modules/core_styles/styles/windows.otui index fe2fe9e6..9b8aac48 100644 --- a/modules/core_styles/styles/windows.otui +++ b/modules/core_styles/styles/windows.otui @@ -1,20 +1,4 @@ Window < UIWindow - font: verdana-11px-antialised - size: 200 200 - opacity: 1 - color: white - text-offset: 0 2 - text-align: top - move-policy: free - stackable: true - image-source: /core_styles/images/window.png - image-border: 4 - image-border-top: 20 - - $disabled: - color: #aaaaaa88 - -Window2 < UIWindow font: verdana-11px-antialised size: 200 200 opacity: 1 @@ -31,7 +15,7 @@ Window2 < UIWindow $disabled: color: #aaaaaa88 -MainWindow < Window2 +MainWindow < Window anchors.centerIn: parent MiniWindow < UIWindow diff --git a/modules/core_widgets/core_widgets.otmod b/modules/core_widgets/core_widgets.otmod index cf721910..332cccd8 100644 --- a/modules/core_widgets/core_widgets.otmod +++ b/modules/core_widgets/core_widgets.otmod @@ -3,6 +3,10 @@ Module description: Contains widgets used by other modules author: OTClient team website: https://github.com/edubart/otclient + reloadable: true + unloadble: false + autoload: true + autoload-antecedence: 40 onLoad: | dofile 'uiwidget' @@ -16,6 +20,12 @@ Module dofile 'uipopupmenu' dofile 'uiwindow' dofile 'uiitem' - dofile 'tooltip/tooltip' - dofile 'messagebox/messagebox' - + dofile 'uimessagebox' + + dofile 'tooltip' + --dofile 'messagebox/messagebox' + + ToolTip.init() + + onUnload: | + ToolTip.terminate() diff --git a/modules/core_widgets/messagebox/messagebox.lua b/modules/core_widgets/messagebox/messagebox.lua deleted file mode 100644 index cd0314fc..00000000 --- a/modules/core_widgets/messagebox/messagebox.lua +++ /dev/null @@ -1,81 +0,0 @@ -MessageBox = {} -MessageBox.__index = MessageBox - --- messagebox flags -MessageBoxOk = 1 -MessageBoxCancel = 2 - -function MessageBox.create(title, text, flags) - local box = {} - setmetatable(box, MessageBox) - - -- create messagebox window - local window = displayUI('messagebox.otui') - window:lock() - window:setText(title) - - local label = window:getChildById('messageBoxLabel') - label:setText(text) - label:resizeToText() - - -- set window size based on label size - window:setWidth(math.max(label:getWidth() + 48, 120)) - window:setHeight(label:getHeight() + 64) - - -- setup messagebox first button - local buttonRight = window:getChildById('messageBoxRightButton') - - if flags == MessageBoxOk then - buttonRight:setText("Ok") - box.onOk = function() end - buttonRight.onClick = function() - box.onOk() - box:destroy() - end - window.onEnter = buttonRight.onClick - window.onEscape = buttonRight.onClick - elseif flags == MessageBoxCancel then - buttonRight:setText("Cancel") - box.onCancel = function() end - buttonRight.onClick = function() - box.onCancel() - box:destroy() - end - window.onEnter = buttonRight.onClick - window.onEscape = buttonRight.onClick - end - - box.window = window - return box -end - -function MessageBox:destroy() - if self.onDestroy then - self.onDestroy() - self.onDestroy = nil - end - if self.window then - self.window:destroy() - self.window = nil - end - self.onOk = nil - self.onCancel = nil -end - --- shortcuts for creating message boxes -function displayMessageBox(title, text, flags) - return MessageBox.create(title, text, flags) -end - -function displayErrorBox(title, text) - return MessageBox.create(title, text, MessageBoxOk) -end - -function displayInfoBox(title, text) - return MessageBox.create(title, text, MessageBoxOk) -end - -function displayCancelBox(title, text) - return MessageBox.create(title, text, MessageBoxCancel) -end - diff --git a/modules/core_widgets/messagebox/messagebox.otui b/modules/core_widgets/messagebox/messagebox.otui deleted file mode 100644 index 4f01f876..00000000 --- a/modules/core_widgets/messagebox/messagebox.otui +++ /dev/null @@ -1,21 +0,0 @@ -Window - id: messageBoxWindow - anchors.centerIn: parent - height: 80 - width: 120 - - Label - id: messageBoxLabel - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - margin-top: 27 - margin-bottom : 27 - - Button - id: messageBoxRightButton - anchors.bottom: parent.bottom - anchors.right: parent.right - margin-right: 10 - margin-bottom: 10 - width: 64 - visible: true diff --git a/modules/core_widgets/tooltip/tooltip.lua b/modules/core_widgets/tooltip.lua similarity index 71% rename from modules/core_widgets/tooltip/tooltip.lua rename to modules/core_widgets/tooltip.lua index 2906767b..8756c8f9 100644 --- a/modules/core_widgets/tooltip/tooltip.lua +++ b/modules/core_widgets/tooltip.lua @@ -6,6 +6,8 @@ local currentHoveredWidget -- private functions local function moveToolTip(tooltip) + if not tooltip:isVisible() then return end + local pos = g_window.getMousePosition() pos.y = pos.y + 1 local xdif = g_window.getSize().width - (pos.x + tooltip:getWidth()) @@ -17,28 +19,6 @@ local function moveToolTip(tooltip) tooltip:setPosition(pos) end --- public functions -function ToolTip.display(text) - if text == nil then return end - ToolTip.hide() - toolTipLabel = createWidget('Label', rootWidget) - toolTipLabel:setId('toolTip') - toolTipLabel:setBackgroundColor('#111111bb') - toolTipLabel:setText(text) - toolTipLabel:resizeToText() - toolTipLabel:resize(toolTipLabel:getWidth() + 4, toolTipLabel:getHeight() + 4) - toolTipLabel.onMouseMove = moveToolTip - moveToolTip(toolTipLabel) -end - -function ToolTip.hide() - if toolTipLabel then - toolTipLabel:destroy() - toolTipLabel = nil - end -end - --- UIWidget hooks local function onWidgetHoverChange(widget, hovered) if hovered then if widget.tooltip then @@ -59,8 +39,39 @@ local function onWidgetStyleApply(widget, styleName, styleNode) end end -connect(UIWidget, { onStyleApply = onWidgetStyleApply, - onHoverChange = onWidgetHoverChange}) +-- public functions +function ToolTip.init() + toolTipLabel = createWidget('Label', rootWidget) + toolTipLabel:setId('toolTip') + toolTipLabel:setBackgroundColor('#111111bb') + connect(toolTipLabel, { onMouseMove = moveToolTip }) + + connect(UIWidget, { onStyleApply = onWidgetStyleApply, + onHoverChange = onWidgetHoverChange}) +end + +function ToolTip.terminate() + disconnect(UIWidget, { onStyleApply = onWidgetStyleApply, + onHoverChange = onWidgetHoverChange }) + + currentHoveredWidget = nil + toolTipLabel:destroy() + toolTipLabel = nil +end + +function ToolTip.display(text) + if text == nil then return end + toolTipLabel:setText(text) + toolTipLabel:resizeToText() + toolTipLabel:resize(toolTipLabel:getWidth() + 4, toolTipLabel:getHeight() + 4) + toolTipLabel:show() + toolTipLabel:raise() + moveToolTip(toolTipLabel) +end + +function ToolTip.hide() + toolTipLabel:hide() +end -- UIWidget extensions function UIWidget:setTooltip(text) diff --git a/modules/core_widgets/tooltip/tooltip.otui b/modules/core_widgets/tooltip/tooltip.otui deleted file mode 100644 index 61b91b35..00000000 --- a/modules/core_widgets/tooltip/tooltip.otui +++ /dev/null @@ -1,7 +0,0 @@ -Label - id: toolTipText - background-color: #111111bb - size: 200 200 - id: toolTip - focusable: false - anchors.centerIn: parent diff --git a/modules/core_widgets/uimessagebox.lua b/modules/core_widgets/uimessagebox.lua index 83e93ce9..7b19151a 100644 --- a/modules/core_widgets/uimessagebox.lua +++ b/modules/core_widgets/uimessagebox.lua @@ -1,23 +1,64 @@ ---[[ UIMessageBox = extends(UIWindow) -function UIMessageBox.create(title, message) +MessageBoxOk = 1 +MessageBoxCancel = 2 + +-- messagebox cannot be created from otui files +UIMessageBox.create = nil + +function UIMessageBox.display(title, message, flags) local messagebox = UIMessageBox.internalCreate() + rootWidget:addChild(messagebox) + messagebox:setStyle('MessageBoxWindow') messagebox:setText(title) - local messageLabel = self:getChildById('messageLabel') - label:setText(message) - label:resizeToText() - window:setWidth(math.max(label:getWidth() + self:getPaddingLeft() + self:getPaddingRight(), self:getWidth())) - window:setHeight(label:getHeight() + self:getPaddingTop() + self:getPaddingBottom()) + local messageLabel = createWidget('MessageBoxLabel', messagebox) + messageLabel:setText(message) + messageLabel:resizeToText() + + messagebox:setWidth(math.max(messageLabel:getWidth() + 48, messagebox:getWidth())) + messagebox:setHeight(math.max(messageLabel:getHeight() + 64, messagebox:getHeight())) + + -- setup messagebox first button + local buttonRight = createWidget('MessageBoxRightButton', messagebox) + + if flags == MessageBoxOk then + buttonRight:setText('Ok') + connect(buttonRight, { onClick = function(self) self:getParent():ok() end }) + elseif flags == MessageBoxCancel then + buttonRight:setText('Cancel') + connect(buttonRight, { onClick = function(self) self:getParent():cancel() end }) + end + + connect(messagebox, { onEnter = function(self) self:destroy() end }) + connect(messagebox, { onEscape = function(self) self:destroy() end }) + + messagebox:lock() return messagebox end -function UIMessageBox:setTitle(title) +function displayInfoBox(title, message) + return UIMessageBox.display(title, message, MessageBoxOk) +end + +function displayErrorBox(title, message) + return UIMessageBox.display(title, message, MessageBoxOk) +end + +function displayCancelBox(title, message) + return UIMessageBox.display(title, message, MessageBoxCancel) +end + +function UIMessageBox:ok() + signalcall(self.onOk, self) + self.onOk = nil + self:destroy() end -function UIMessageBox:setMessage(message) +function UIMessageBox:cancel() + signalcall(self.onCancel, self) + self.onCancel = nil + self:destroy() end -]]-- \ No newline at end of file diff --git a/modules/game/game.lua b/modules/game/game.lua index 353bd445..21d8cb4e 100644 --- a/modules/game/game.lua +++ b/modules/game/game.lua @@ -90,13 +90,13 @@ end function Game.onLoginError(message) CharacterList.destroyLoadBox() local errorBox = displayErrorBox("Login Error", "Login error: " .. message) - errorBox.onOk = CharacterList.show + connect(errorBox, { onOk = CharacterList.show }) end function Game.onConnectionError(message) CharacterList.destroyLoadBox() local errorBox = displayErrorBox("Login Error", "Connection error: " .. message) - errorBox.onOk = CharacterList.show + connect(errorBox, { onOk = CharacterList.show }) end local function onApplicationClose() diff --git a/modules/game/game.otui b/modules/game/game.otui index baa5ca45..133eae1e 100644 --- a/modules/game/game.otui +++ b/modules/game/game.otui @@ -30,5 +30,4 @@ UIGame id: mouseGrabber focusable: false visible: false - phantom: true diff --git a/src/framework/core/eventdispatcher.h b/src/framework/core/eventdispatcher.h index f7afade3..ac397ed9 100644 --- a/src/framework/core/eventdispatcher.h +++ b/src/framework/core/eventdispatcher.h @@ -33,7 +33,7 @@ public: Event(const SimpleCallback& callback) : m_callback(callback), m_canceled(false), m_executed(false) { } void execute() { - if(!m_canceled && !m_executed) { + if(!m_canceled && !m_executed && m_callback) { m_callback(); m_executed = true; } diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index c1fad18a..f5017d44 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -52,8 +52,10 @@ bool Module::load() if(m_loadCallback) m_loadCallback(); - logInfo("Loaded module '", m_name, "'"); m_loaded = true; + logInfo("Loaded module '", m_name, "'"); + g_modules.updateModuleLoadOrder(asModule()); + return true; } @@ -63,9 +65,33 @@ void Module::unload() if(m_unloadCallback) m_unloadCallback(); m_loaded = false; + logInfo("Unloaded module '", m_name, "'"); + g_modules.updateModuleLoadOrder(asModule()); } } +bool Module::reload() +{ + unload(); + return load(); +} + +bool Module::isDependent() +{ + for(const ModulePtr& module : g_modules.getModules()) { + if(module->isLoaded() && module->hasDependency(m_name)) + return true; + } + return false; +} + +bool Module::hasDependency(const std::string& name) +{ + if(std::find(m_dependencies.begin(), m_dependencies.end(), name) != m_dependencies.end()) + return true; + return false; +} + void Module::discover(const OTMLNodePtr& moduleNode) { const static std::string none = "none"; @@ -73,8 +99,9 @@ void Module::discover(const OTMLNodePtr& moduleNode) m_author = moduleNode->valueAt("author", none); m_website = moduleNode->valueAt("website", none); m_version = moduleNode->valueAt("version", none); - m_autoLoad = moduleNode->valueAt("autoLoad", false); - m_autoLoadAntecedence = moduleNode->valueAt("autoLoadAntecedence", 100); + m_autoLoad = moduleNode->valueAt("autoload", false); + m_unloadable = moduleNode->valueAt("unloadable", true); + m_autoLoadAntecedence = moduleNode->valueAt("autoload-antecedence", 9999); if(OTMLNodePtr node = moduleNode->get("dependencies")) { for(const OTMLNodePtr& tmp : node->children()) @@ -95,4 +122,3 @@ void Module::discover(const OTMLNodePtr& moduleNode) m_unloadCallback = g_lua.polymorphicPop(); } } - diff --git a/src/framework/core/module.h b/src/framework/core/module.h index 8b64373c..781aaa11 100644 --- a/src/framework/core/module.h +++ b/src/framework/core/module.h @@ -35,8 +35,12 @@ public: bool load(); void unload(); + bool reload(); + bool canUnload() { return m_loaded && m_unloadable && !isDependent(); } bool isLoaded() { return m_loaded; } + bool isDependent(); + bool hasDependency(const std::string& name); std::string getDescription() { return m_description; } std::string getName() { return m_name; } @@ -46,6 +50,8 @@ public: bool isAutoLoad() { return m_autoLoad; } int getAutoLoadAntecedence() { return m_autoLoadAntecedence; } + ModulePtr asModule() { return std::static_pointer_cast(shared_from_this()); } + protected: void discover(const OTMLNodePtr& moduleNode); friend class ModuleManager; @@ -53,6 +59,7 @@ protected: private: Boolean m_loaded; Boolean m_autoLoad; + Boolean m_unloadable; int m_autoLoadAntecedence; std::string m_name; std::string m_description; diff --git a/src/framework/core/modulemanager.cpp b/src/framework/core/modulemanager.cpp index 699436af..24c406bd 100644 --- a/src/framework/core/modulemanager.cpp +++ b/src/framework/core/modulemanager.cpp @@ -61,13 +61,13 @@ void ModuleManager::autoLoadModules(int maxAntecedence) void ModuleManager::discoverModulesPath() { // search for modules directory - std::string possibleDirs[] = { "modules", - g_resources.getBaseDir() + "modules", - g_resources.getBaseDir() + "../modules", - g_resources.getBaseDir() + "../share/" + g_app->getAppName() + "/modules", - "" }; + std::string possibleModulesDirs[] = { "modules", + g_resources.getBaseDir() + "modules", + g_resources.getBaseDir() + "../modules", + g_resources.getBaseDir() + "../share/" + g_app->getAppName() + "/modules", + "" }; bool found = false; - for(const std::string& dir : possibleDirs) { + for(const std::string& dir : possibleModulesDirs) { // try to add module directory if(g_resources.addToSearchPath(dir, false)) { logInfo("Using modules directory '", dir.c_str(), "'"); @@ -78,6 +78,21 @@ void ModuleManager::discoverModulesPath() if(!found) logFatal("Could not find modules directory"); + + // search for addons directory + std::string possibleAddonsDirs[] = { "addons", + g_resources.getBaseDir() + "addons", + g_resources.getBaseDir() + "../addons", + g_resources.getBaseDir() + "../addons/" + g_app->getAppName() + "/modules", + "" }; + for(const std::string& dir : possibleAddonsDirs) { + // try to add module directory + if(g_resources.addToSearchPath(dir, false)) { + logInfo("Using addons directory '", dir.c_str(), "'"); + found = true; + break; + } + } } ModulePtr ModuleManager::discoverModule(const std::string& moduleFile) @@ -99,6 +114,7 @@ ModulePtr ModuleManager::discoverModule(const std::string& moduleFile) } module->discover(moduleNode); + // not loaded modules are always in back if(push) m_modules.push_back(module); } catch(Exception& e) { @@ -116,10 +132,30 @@ void ModuleManager::ensureModuleLoaded(const std::string& moduleName) void ModuleManager::unloadModules() { - for(const ModulePtr& module : m_modules) + auto modulesBackup = m_modules; + for(const ModulePtr& module : modulesBackup) module->unload(); } +void ModuleManager::reloadModules() +{ + std::deque toLoadList; + + // unload in the reverse direction, try to unload upto 10 times (because of dependencies) + for(int i=0;i<10;++i) { + auto modulesBackup = m_modules; + for(const ModulePtr& module : modulesBackup) { + if(module->isLoaded() && module->canUnload()) { + module->unload(); + toLoadList.push_front(module); + } + } + } + + for(const ModulePtr& module : toLoadList) + module->load(); +} + ModulePtr ModuleManager::getModule(const std::string& moduleName) { for(const ModulePtr& module : m_modules) @@ -127,3 +163,14 @@ ModulePtr ModuleManager::getModule(const std::string& moduleName) return module; return nullptr; } + +void ModuleManager::updateModuleLoadOrder(ModulePtr module) +{ + auto it = std::find(m_modules.begin(), m_modules.end(), module); + if(it != m_modules.end()) + m_modules.erase(it); + if(module->isLoaded()) + m_modules.push_front(module); + else + m_modules.push_back(module); +} diff --git a/src/framework/core/modulemanager.h b/src/framework/core/modulemanager.h index c75499df..957d8f57 100644 --- a/src/framework/core/modulemanager.h +++ b/src/framework/core/modulemanager.h @@ -34,12 +34,18 @@ public: ModulePtr discoverModule(const std::string& moduleFile); void ensureModuleLoaded(const std::string& moduleName); void unloadModules(); + void reloadModules(); ModulePtr getModule(const std::string& moduleName); - std::vector getModules() { return m_modules; } + std::deque getModules() { return m_modules; } + +protected: + void updateModuleLoadOrder(ModulePtr module); + + friend class Module; private: - std::vector m_modules; + std::deque m_modules; std::multimap m_autoLoadModules; }; diff --git a/src/framework/graphics/fontmanager.cpp b/src/framework/graphics/fontmanager.cpp index 8e8bb2a7..9cd888ed 100644 --- a/src/framework/graphics/fontmanager.cpp +++ b/src/framework/graphics/fontmanager.cpp @@ -48,8 +48,16 @@ bool FontManager::importFont(std::string fontFile) OTMLNodePtr fontNode = doc->at("Font"); std::string name = fontNode->valueAt("name"); - if(fontExists(name)) - Fw::throwException("font '", name, "' already exists, cannot have duplicate font names"); + //if(fontExists(name)) + // Fw::throwException("font '", name, "' already exists, cannot have duplicate font names"); + + // remove any font with the same name + for(auto it = m_fonts.begin(); it != m_fonts.end(); ++it) { + if((*it)->getName() == name) { + m_fonts.erase(it); + break; + } + } FontPtr font(new Font(name)); font->load(fontNode); diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 3c29d702..4fd8ea4b 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -47,11 +47,15 @@ void Application::registerLuaFunctions() // Event g_lua.registerClass(); + g_lua.bindClassMemberFunction("cancel", &Event::cancel); + g_lua.bindClassMemberFunction("execute", &Event::execute); g_lua.bindClassMemberFunction("isCanceled", &Event::isCanceled); g_lua.bindClassMemberFunction("isExecuted", &Event::isExecuted); // ScheduledEvent g_lua.registerClass(); + g_lua.bindClassMemberFunction("reamaningTicks", &ScheduledEvent::reamaningTicks); + g_lua.bindClassMemberFunction("ticks", &ScheduledEvent::ticks); // UIWidget g_lua.registerClass(); @@ -370,6 +374,8 @@ void Application::registerLuaFunctions() g_lua.registerClass(); g_lua.bindClassMemberFunction("load", &Module::load); g_lua.bindClassMemberFunction("unload", &Module::unload); + g_lua.bindClassMemberFunction("reload", &Module::reload); + g_lua.bindClassMemberFunction("canUnload", &Module::canUnload); g_lua.bindClassMemberFunction("isLoaded", &Module::isLoaded); g_lua.bindClassMemberFunction("getDescription", &Module::getDescription); g_lua.bindClassMemberFunction("getName", &Module::getName); @@ -397,6 +403,8 @@ void Application::registerLuaFunctions() // Application g_lua.registerStaticClass("g_app"); g_lua.bindClassStaticFunction("g_app", "exit", std::bind(&Application::exit, g_app)); + g_lua.bindClassStaticFunction("g_app", "isRunning", std::bind(&Application::isRunning, g_app)); + g_lua.bindClassStaticFunction("g_app", "isStopping", std::bind(&Application::isStopping, g_app)); // ConfigManager g_lua.registerStaticClass("g_configs"); @@ -477,6 +485,7 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("g_modules", "discoverModule", std::bind(&ModuleManager::discoverModule, &g_modules, _1)); g_lua.bindClassStaticFunction("g_modules", "ensureModuleLoaded", std::bind(&ModuleManager::ensureModuleLoaded, &g_modules, _1)); g_lua.bindClassStaticFunction("g_modules", "unloadModules", std::bind(&ModuleManager::unloadModules, &g_modules)); + g_lua.bindClassStaticFunction("g_modules", "reloadModules", std::bind(&ModuleManager::reloadModules, &g_modules)); g_lua.bindClassStaticFunction("g_modules", "getModule", std::bind(&ModuleManager::getModule, &g_modules, _1)); g_lua.bindClassStaticFunction("g_modules", "getModules", std::bind(&ModuleManager::getModules, &g_modules)); diff --git a/src/framework/luascript/luavaluecasts.h b/src/framework/luascript/luavaluecasts.h index a45d2137..5b4f5b94 100644 --- a/src/framework/luascript/luavaluecasts.h +++ b/src/framework/luascript/luavaluecasts.h @@ -132,6 +132,9 @@ bool luavalue_cast(int index, std::vector& vec); template void push_luavalue(const std::deque& vec); +template +bool luavalue_cast(int index, std::deque& vec); + // tuple template void push_luavalue(const std::tuple& tuple); @@ -279,6 +282,22 @@ void push_luavalue(const std::deque& vec) { } } +template +bool luavalue_cast(int index, std::deque& vec) +{ + if(g_lua.isTable(index)) { + g_lua.pushNil(); + while(g_lua.next(index < 0 ? index-1 : index)) { + T value; + if(luavalue_cast(-1, value)) + vec.push_back(value); + g_lua.pop(); + } + return true; + } + return false; +} + template struct push_tuple_luavalue { template diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index eee0b97e..63e9ee9b 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -554,15 +554,17 @@ void UIWidget::destroy() #ifdef DEBUG auto self = asUIWidget(); - g_lua.collectGarbage(); - g_dispatcher.addEvent([self] { + if(self != g_ui.getRootWidget()) { g_lua.collectGarbage(); g_dispatcher.addEvent([self] { g_lua.collectGarbage(); - if(self->getUseCount() != 1) - logWarning("widget '", self->getId(), "' destroyed but still have ", self->getUseCount()-1, " reference(s) left"); + g_dispatcher.addEvent([self] { + g_lua.collectGarbage(); + if(self->getUseCount() != 1) + logWarning("widget '", self->getId(), "' destroyed but still have ", self->getUseCount()-1, " reference(s) left"); + }); }); - }); + } #endif m_destroyed = true; @@ -853,9 +855,9 @@ UIWidgetPtr UIWidget::getChildById(const std::string& childId) UIWidgetPtr UIWidget::getChildByPos(const Point& childPos) { for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { - const UIWidgetPtr& widget = (*it); - if(widget->isExplicitlyVisible() && widget->containsPoint(childPos)) - return widget; + const UIWidgetPtr& child = (*it); + if(child->isExplicitlyVisible() && child->containsPoint(childPos)) + return child; } return nullptr; @@ -884,7 +886,8 @@ UIWidgetPtr UIWidget::recursiveGetChildById(const std::string& id) UIWidgetPtr UIWidget::recursiveGetChildByPos(const Point& childPos) { - for(const UIWidgetPtr& child : m_children) { + for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { + const UIWidgetPtr& child = (*it); if(child->isExplicitlyVisible() && child->containsPoint(childPos)) { if(UIWidgetPtr subChild = child->recursiveGetChildByPos(childPos)) return subChild; @@ -1280,9 +1283,9 @@ bool UIWidget::propagateOnKeyPress(uchar keyCode, int keyboardModifiers, int aut return true; } - if(autoRepeatTicks == 0 || autoRepeatTicks >= m_autoRepeatDelay) { + if(autoRepeatTicks == 0 || autoRepeatTicks >= m_autoRepeatDelay) return onKeyPress(keyCode, keyboardModifiers, autoRepeatTicks); - } else + else return false; } diff --git a/src/framework/ui/uiwidgettext.cpp b/src/framework/ui/uiwidgettext.cpp index ad386ee6..672c2e8b 100644 --- a/src/framework/ui/uiwidgettext.cpp +++ b/src/framework/ui/uiwidgettext.cpp @@ -86,7 +86,7 @@ void UIWidget::onFontChange(const std::string& font) void UIWidget::wrapText() { - setText(m_font->wrapText(m_text, getWidth())); + setText(m_font->wrapText(m_text, getWidth() - m_textOffset.x)); } void UIWidget::setText(const std::string& text) diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index d068af43..6cbf52c8 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -37,11 +37,18 @@ void OTClient::init(const std::vector& args) Application::init(args, Fw::AppEnableAll); g_modules.discoverModules(); - g_modules.autoLoadModules(100); - g_modules.ensureModuleLoaded("client"); - g_modules.autoLoadModules(1000); - //g_map.load(); + // core modules 0-99 + g_modules.autoLoadModules(99); + g_modules.ensureModuleLoaded("core_lib"); + // client modules 100-499 + g_modules.autoLoadModules(499); + g_modules.ensureModuleLoaded("client_main"); + // game modules 500-999 + g_modules.autoLoadModules(999); + g_modules.ensureModuleLoaded("game"); + // addons 1000-9999 + g_modules.autoLoadModules(9999); // load otclientrc.lua if(g_resources.fileExists("/otclientrc.lua")) {