From 44a20222bb063d4f284b2cdb76f38e9351aff4fd Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 15 Jan 2012 19:19:52 -0200 Subject: [PATCH] walk and key event system rework with some regressions --- TODO | 6 +- modules/addon_pingbar/pingbar.lua | 2 +- modules/addon_pingbar/pingbar.otmod | 2 +- modules/addon_terminal/terminal.lua | 14 +-- modules/client_entergame/characterlist.lua | 3 +- modules/client_entergame/entergame.lua | 4 +- modules/client_options/options.lua | 4 +- modules/client_topmenu/topmenu.lua | 4 +- modules/core_lib/const.lua | 9 ++ modules/core_lib/hotkeys.lua | 50 +++++++-- modules/core_widgets/uipopupmenu.lua | 5 +- modules/core_widgets/uiwindow.lua | 3 +- modules/game/game.lua | 14 ++- modules/game_console/console.lua | 8 +- modules/otclientrc.lua | 14 +-- src/framework/const.h | 2 + src/framework/core/configmanager.cpp | 4 +- src/framework/core/inputevent.h | 20 +++- src/framework/graphics/particle.cpp | 10 +- src/framework/graphics/particle.h | 6 +- src/framework/graphics/particleaffector.cpp | 4 +- src/framework/graphics/particleaffector.h | 2 +- src/framework/graphics/particleemitter.cpp | 6 +- src/framework/graphics/particleemitter.h | 2 +- src/framework/luafunctions.cpp | 5 +- src/framework/platform/platformwindow.cpp | 81 ++++++++++++++ src/framework/platform/platformwindow.h | 17 +++ src/framework/platform/win32window.cpp | 1 - src/framework/platform/win32window.h | 1 - src/framework/platform/x11window.cpp | 115 ++++++++++---------- src/framework/platform/x11window.h | 1 - src/framework/ui/uilineedit.cpp | 59 +++++----- src/framework/ui/uilineedit.h | 3 +- src/framework/ui/uimanager.cpp | 10 +- src/framework/ui/uiwidget.cpp | 74 +++++++++++-- src/framework/ui/uiwidget.h | 12 +- src/otclient/core/creature.cpp | 106 +++++++++--------- src/otclient/core/creature.h | 11 +- src/otclient/core/game.cpp | 37 ++++--- src/otclient/core/game.h | 1 + src/otclient/core/localplayer.cpp | 77 ++----------- src/otclient/core/localplayer.h | 10 +- src/otclient/core/missile.cpp | 12 +- src/otclient/core/missile.h | 2 +- src/otclient/core/thing.h | 7 +- src/otclient/core/tile.cpp | 12 +- src/otclient/core/tile.h | 5 +- src/otclient/luafunctions.cpp | 2 + src/otclient/net/protocolgameparse.cpp | 4 +- src/otclient/ui/uigame.cpp | 17 ++- src/otclient/ui/uigame.h | 4 +- src/otclient/util/position.h | 2 +- 52 files changed, 541 insertions(+), 345 deletions(-) diff --git a/TODO b/TODO index d99b7181..866dbd5c 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ ==================================================== High priority TODO in order (before first public disclose) -[bart] tab widgets [bart] chat with tabs [bart] scrollbar [bart] scrollable widgets @@ -62,8 +61,10 @@ change win32 mouse cursor icon [bart] review and make more error prone with more warnings [bart] reapply anchor styles when adding new childs [bart] ui text selection +[bart] find styles by scope [bart] make set of background/icon/image width alone work [bart] check for recursive anchors and print a error instead of crashing +[bart] make api to enable/disable capture of events to avoid massive event processing == Client modules [bart] make possible to reload modules @@ -73,11 +74,12 @@ change win32 mouse cursor icon [bart] clean sprites cache periodically [bart] create a shader manager [bart] find a way to load map rendering styles +[bart] move redering of creatures names, skulls, etc to UI [bart] cache screen creatures in a list on map [bart] handle corrupt errors in dat/spr [bart] remake spr/dat using OTML and image files [bart] rework map tile rendering (cache visible tiles, etc) -[bart] minimap windows +[bart] minimap window [bart] draw lights using shaders [bart] limit FPS in options [bart] resize map, right panel diff --git a/modules/addon_pingbar/pingbar.lua b/modules/addon_pingbar/pingbar.lua index 88e1dc22..18eef16b 100644 --- a/modules/addon_pingbar/pingbar.lua +++ b/modules/addon_pingbar/pingbar.lua @@ -8,7 +8,7 @@ function PingBar.init() pingLabel:applyStyle({ ['anchors.left'] = 'prev.right', ['anchors.top'] = 'parent.top', ['margin-top'] = 12, - ['margin-left'] = 10, + ['margin-left'] = 20, font = 'verdana-11px-rounded', color = '#FE6500', width = 120, diff --git a/modules/addon_pingbar/pingbar.otmod b/modules/addon_pingbar/pingbar.otmod index b495e99d..f55172ca 100644 --- a/modules/addon_pingbar/pingbar.otmod +++ b/modules/addon_pingbar/pingbar.otmod @@ -4,7 +4,7 @@ Module author: OTClient team website: https://github.com/edubart/otclient - autoLoad: false + autoLoad: true autoLoadAntecedence: 1000 onLoad: | diff --git a/modules/addon_terminal/terminal.lua b/modules/addon_terminal/terminal.lua index 4d661b95..fb951aed 100644 --- a/modules/addon_terminal/terminal.lua +++ b/modules/addon_terminal/terminal.lua @@ -108,16 +108,16 @@ function Terminal.init() terminalWidget:setVisible(false) terminalButton = TopMenu.addButton('terminalButton', 'Terminal (Ctrl + T)', '/core_styles/icons/terminal.png', Terminal.toggle) - Hotkeys.bind('Ctrl+T', Terminal.toggle) + Hotkeys.bindKeyDown('Ctrl+T', Terminal.toggle) commandHistory = Settings.getList('terminal-history') commandLineEdit = terminalWidget:getChildById('commandLineEdit') - Hotkeys.bind('Up', function() navigateCommand(1) end, commandLineEdit) - Hotkeys.bind('Down', function() navigateCommand(-1) end, commandLineEdit) - Hotkeys.bind('Tab', completeCommand, commandLineEdit) - Hotkeys.bind('Enter', doCommand, commandLineEdit) - Hotkeys.bind('Return', doCommand, commandLineEdit) + Hotkeys.bindKeyDown('Up', function() navigateCommand(1) end, commandLineEdit) + Hotkeys.bindKeyDown('Down', function() navigateCommand(-1) end, commandLineEdit) + Hotkeys.bindKeyDown('Tab', completeCommand, commandLineEdit) + Hotkeys.bindKeyDown('Enter', doCommand, commandLineEdit) + Hotkeys.bindKeyDown('Return', doCommand, commandLineEdit) terminalBuffer = terminalWidget:getChildById('terminalBuffer') Logger.setOnLog(onLog) @@ -126,7 +126,7 @@ end function Terminal.terminate() Settings.setList('terminal-history', commandHistory) - Hotkeys.unbind('Ctrl+T') + Hotkeys.unbindKeyDown('Ctrl+T') Logger.setOnLog(nil) terminalButton:destroy() terminalButton = nil diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index 7704659e..71e7ee8a 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -6,7 +6,8 @@ local loadBox local characterList -- private functions -local function onCharactersWindowKeyPress(self, keyCode, keyText, keyboardModifiers) +local function onCharactersWindowKeyPress(self, keyCode, keyboardModifiers, wouldFilter) + if wouldFilter then return end if keyboardModifiers == KeyboardNoModifier then if keyCode == KeyUp then characterList:focusPreviousChild(ActiveFocusReason) diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index d22a2c20..7ac44f64 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -57,7 +57,7 @@ end -- public functions function EnterGame.init() enterGameButton = TopMenu.addButton('enterGameButton', 'Login (Ctrl + G)', '/core_styles/icons/login.png', EnterGame.openWindow) - Hotkeys.bind('Ctrl+G', EnterGame.openWindow) + Hotkeys.bindKeyDown('Ctrl+G', EnterGame.openWindow) motdButton = TopMenu.addButton('motdButton', 'Message of the day', '/core_styles/icons/motd.png', EnterGame.displayMotd) motdButton:hide() enterGame = displayUI('entergame.otui') @@ -82,7 +82,7 @@ function EnterGame.init() end function EnterGame.terminate() - Hotkeys.unbind('Ctrl+G') + Hotkeys.unbindKeyDown('Ctrl+G') enterGame:destroy() enterGame = nil enterGameButton:destroy() diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index 7a7ecde8..8f617452 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -25,11 +25,11 @@ function Options.init() optionsWindow = displayUI('options.otui') optionsWindow:setVisible(false) optionsButton = TopMenu.addButton('settingsButton', 'Options (Ctrl+O)', '/core_styles/icons/settings.png', Options.toggle) - Hotkeys.bind('Ctrl+O', Options.toggle) + Hotkeys.bindKeyDown('Ctrl+O', Options.toggle) end function Options.terminate() - Hotkeys.unbind('Ctrl+O') + Hotkeys.unbindKeyDown('Ctrl+O') optionsWindow:destroy() optionsWindow = nil optionsButton:destroy() diff --git a/modules/client_topmenu/topmenu.lua b/modules/client_topmenu/topmenu.lua index 72406cbe..c06b4f69 100644 --- a/modules/client_topmenu/topmenu.lua +++ b/modules/client_topmenu/topmenu.lua @@ -23,11 +23,11 @@ function TopMenu.init() gameButtonsPanel = topMenu:getChildById('gameButtonsPanel') TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout) - Hotkeys.bind('Ctrl+Q', onLogout) + Hotkeys.bindKeyDown('Ctrl+Q', onLogout) end function TopMenu.terminate() - Hotkeys.unbind('Ctrl+Q') + Hotkeys.unbindKeyDown('Ctrl+Q') leftButtonsPanel = nil rightButtonsPanel = nil topMenu:destroy() diff --git a/modules/core_lib/const.lua b/modules/core_lib/const.lua index d63a59f4..654bcc76 100644 --- a/modules/core_lib/const.lua +++ b/modules/core_lib/const.lua @@ -45,6 +45,15 @@ AlignTopCenter = 20 AlignBottomCenter = 24 AlignCenter = 48 +North = 0 +East = 1 +South = 2 +West = 3 +NorthEast = 4 +SouthEast = 5 +SouthWest = 6 +NorthWest = 7 + KeyUnknown = 0 KeyEscape = 1 diff --git a/modules/core_lib/hotkeys.lua b/modules/core_lib/hotkeys.lua index 4780c8eb..e3fab6ba 100644 --- a/modules/core_lib/hotkeys.lua +++ b/modules/core_lib/hotkeys.lua @@ -58,10 +58,10 @@ local function determineKeyComboDesc(keyCode, keyboardModifiers) return translateKeyCombo(keyCombo) end -local function onWidgetKeyPress(widget, keyCode, keyText, keyboardModifiers) +local function onWidgetKeyDown(widget, keyCode, keyboardModifiers) if keyCode == KeyUnknown then return end local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers) - local callback = widget.boundKeyCombos[keyComboDesc] + local callback = widget.boundKeyDownCombos[keyComboDesc] if callback then callback() return true @@ -69,29 +69,57 @@ local function onWidgetKeyPress(widget, keyCode, keyText, keyboardModifiers) return false end -local function connectWidgetHotkeyEvent(widget) - if widget.boundKeyCombos then return end +local function onWidgetKeyPress(widget, keyCode, keyboardModifiers, wouldFilter) + local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers) + if keyCode == KeyUnknown then return end + local callback = widget.boundKeyPressCombos[keyComboDesc] + if callback then + callback() + return true + end + return false +end + +local function connectKeyDownEvent(widget) + if widget.boundKeyDownCombos then return end + connect(widget, { onKeyDown = onWidgetKeyDown }) + widget.boundKeyDownCombos = {} +end + +local function connectKeyPressEvent(widget) + if widget.boundKeyPressCombos then return end connect(widget, { onKeyPress = onWidgetKeyPress }) - widget.boundKeyCombos = {} + widget.boundKeyPressCombos = {} end -- public functions -function Hotkeys.bind(keyComboDesc, callback, widget) +function Hotkeys.bindKeyDown(keyComboDesc, callback, widget) + widget = widget or rootWidget + connectKeyDownEvent(widget) + local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) + if keyComboDesc then + widget.boundKeyDownCombos[keyComboDesc] = callback + else + error('key combo \'' .. keyComboDesc .. '\' is failed') + end +end + +function Hotkeys.bindKeyPress(keyComboDesc, callback, widget) widget = widget or rootWidget - connectWidgetHotkeyEvent(widget) + connectKeyPressEvent(widget) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) if keyComboDesc then - widget.boundKeyCombos[keyComboDesc] = callback + widget.boundKeyPressCombos[keyComboDesc] = callback else error('key combo \'' .. keyComboDesc .. '\' is failed') end end -function Hotkeys.unbind(keyComboDesc, widget) +function Hotkeys.unbindKeyDown(keyComboDesc, widget) widget = widget or rootWidget - if widget.boundKeyCombos == nil then return end + if widget.boundKeyDownCombos == nil then return end local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) if keyComboDesc then - widget.boundKeyCombos[keyComboDesc] = nil + widget.boundKeyDownCombos[keyComboDesc] = nil end end diff --git a/modules/core_widgets/uipopupmenu.lua b/modules/core_widgets/uipopupmenu.lua index 1a676ac9..5b560424 100644 --- a/modules/core_widgets/uipopupmenu.lua +++ b/modules/core_widgets/uipopupmenu.lua @@ -5,7 +5,7 @@ local displayedMenuList = {} function UIPopupMenu.create() local menu = UIPopupMenu.internalCreate() local layout = UIVerticalLayout.create(menu) - layout:setFitParent(true) + layout:setFitChildren(true) menu:setLayout(layout) return menu end @@ -53,7 +53,8 @@ function UIPopupMenu:onMousePress(mousePos, mouseButton) return false end -function UIPopupMenu:onKeyPress(keyCode, keyText, keyboardModifiers) +function UIPopupMenu:onKeyPress(keyCode, keyboardModifiers, wouldFilter) + if wouldFilter then return end if keyCode == KeyEscape then self:destroy() return true diff --git a/modules/core_widgets/uiwindow.lua b/modules/core_widgets/uiwindow.lua index b7de05a0..d80b23c1 100644 --- a/modules/core_widgets/uiwindow.lua +++ b/modules/core_widgets/uiwindow.lua @@ -6,7 +6,8 @@ function UIWindow.create() return window end -function UIWindow:onKeyPress(keyCode, keyText, keyboardModifiers) +function UIWindow:onKeyPress(keyCode, keyboardModifiers, wouldFilter) + if wouldFilter then return end if keyboardModifiers == KeyboardNoModifier then if keyCode == KeyReturn or keyCode == KeyEnter then signalcall(self.onEnter, self) diff --git a/modules/game/game.lua b/modules/game/game.lua index 8727e86f..08287f07 100644 --- a/modules/game/game.lua +++ b/modules/game/game.lua @@ -1,5 +1,6 @@ -- private functions -local function onGameKeyPress(self, keyCode, keyText, keyboardModifiers) +local function onGameKeyPress(self, keyCode, keyboardModifiers, wouldFilter) + if wouldFilter then return end if keyboardModifiers == KeyboardCtrlModifier then if keyCode == KeyG then CharacterList.show() @@ -17,6 +18,17 @@ function Game.createInterface() Background.hide() CharacterList.destroyLoadBox() Game.gameUi = displayUI('game.otui') + + --Hotkeys.bindKeyPress('Up', function() Game.walk(North) end) + --Hotkeys.bindKeyPress('Down', function() Game.walk(South) end) + --Hotkeys.bindKeyPress('Left', function() Game.walk(West) end) + --Hotkeys.bindKeyPress('Right', function() Game.walk(East) end) + + Hotkeys.bindKeyPress('Ctrl+Shift+Up', function() Game.forceWalk(North) end) + Hotkeys.bindKeyPress('Ctrl+Shift+Down', function() Game.forceWalk(South) end) + Hotkeys.bindKeyPress('Ctrl+Shift+Left', function() Game.forceWalk(West) end) + Hotkeys.bindKeyPress('Ctrl+Shift+Right', function() Game.forceWalk(East) end) + rootWidget:moveChildToIndex(Game.gameUi, 1) Game.gameMapPanel = Game.gameUi:getChildById('gameMapPanel') Game.gameRightPanel = Game.gameUi:getChildById('gameRightPanel') diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index 3ba7b502..9df8a0c6 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -48,10 +48,10 @@ function Console.create() Console.addChannel('Default', 0) Console.addTab('Server Log') - Hotkeys.bind('Tab', function() consoleTabBar:selectNextTab() end, consolePanel) - Hotkeys.bind('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel) - Hotkeys.bind('Enter', Console.sendCurrentMessage, consolePanel) - Hotkeys.bind('Return', Console.sendCurrentMessage, consolePanel) + Hotkeys.bindKeyDown('Tab', function() consoleTabBar:selectNextTab() end, consolePanel) + Hotkeys.bindKeyDown('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel) + Hotkeys.bindKeyDown('Enter', Console.sendCurrentMessage, consolePanel) + Hotkeys.bindKeyDown('Return', Console.sendCurrentMessage, consolePanel) end function Console.destroy() diff --git a/modules/otclientrc.lua b/modules/otclientrc.lua index 93b8ab33..7f3ce821 100644 --- a/modules/otclientrc.lua +++ b/modules/otclientrc.lua @@ -1,18 +1,18 @@ -- this file use loaded after everything is loaded and initialized -- you can place any custom user code here -Hotkeys.bind('F1', function() Game.talk('exura gran') end) -Hotkeys.bind('F2', function() Game.talk('exori mort') end) -Hotkeys.bind('F3', function() Game.talk('exori frigo') end) -Hotkeys.bind('F4', function() Game.talk('exevo vis hur') end) -Hotkeys.bind('F5', function() Game.talk('utani gran hur') end) -Hotkeys.bind('F6', function() Game.talk('exani tera') end) +Hotkeys.bindKeyDown('F1', function() Game.talk('exura gran') end) +Hotkeys.bindKeyDown('F2', function() Game.talk('exori mort') end) +Hotkeys.bindKeyDown('F3', function() Game.talk('exori frigo') end) +Hotkeys.bindKeyDown('F4', function() Game.talk('exevo vis hur') end) +Hotkeys.bindKeyDown('F5', function() Game.talk('utani gran hur') end) +Hotkeys.bindKeyDown('F6', function() Game.talk('exani tera') end) local function reload() runscript('otclientrc.lua') TextMessage.displayEventAdvance('Script otclientrc.lua reloaded.') print('Script otclient.rc lua reloaded') end -Hotkeys.bind('Ctrl+R', reload) +Hotkeys.bindKeyDown('Ctrl+R', reload) rcloaded = true diff --git a/src/framework/const.h b/src/framework/const.h index 5275e3fb..ddadceae 100644 --- a/src/framework/const.h +++ b/src/framework/const.h @@ -228,6 +228,8 @@ namespace Fw enum InputEventType { NoInputEvent = 0, + KeyTextInputEvent, + KeyDownInputEvent, KeyPressInputEvent, KeyReleaseInputEvent, MousePressInputEvent, diff --git a/src/framework/core/configmanager.cpp b/src/framework/core/configmanager.cpp index a88a6365..fc1ade93 100644 --- a/src/framework/core/configmanager.cpp +++ b/src/framework/core/configmanager.cpp @@ -76,10 +76,8 @@ void ConfigManager::setList(const std::string& key, const std::vectorwriteIn(value); - dump << "insert" << value; - } m_confsDoc->addChild(child); } diff --git a/src/framework/core/inputevent.h b/src/framework/core/inputevent.h index 9b9bd6fd..a6e098a9 100644 --- a/src/framework/core/inputevent.h +++ b/src/framework/core/inputevent.h @@ -26,14 +26,30 @@ #include "declarations.h" struct InputEvent { + InputEvent() { + reset(); + keyboardModifiers = 0; + } + + void reset(Fw::InputEventType eventType = Fw::NoInputEvent) { + type = eventType; + wheelDirection = Fw::MouseNoWheel; + mouseButton = Fw::MouseNoButton; + keyCode = Fw::KeyUnknown; + keyText = ""; + mouseMoved = Point(); + wouldFilter = false; + }; + Fw::InputEventType type; Fw::MouseWheelDirection wheelDirection; Fw::MouseButton mouseButton; - int keyboardModifiers; - std::string keyText; Fw::Key keyCode; + std::string keyText; + int keyboardModifiers; Point mousePos; Point mouseMoved; + bool wouldFilter; }; #endif diff --git a/src/framework/graphics/particle.cpp b/src/framework/graphics/particle.cpp index 91f8700a..972dd791 100644 --- a/src/framework/graphics/particle.cpp +++ b/src/framework/graphics/particle.cpp @@ -29,7 +29,7 @@ Particle::Particle(const Point& pos, const Size& startSize, const Size& finalSiz m_colors = colors; m_colorsStops = colorsStops; - m_position = PointF(pos.x, pos.y); + m_pos = PointF(pos.x, pos.y); m_startSize = startSize; m_finalSize = finalSize; m_velocity = velocity; @@ -80,18 +80,18 @@ void Particle::updatePosition(double elapsedTime) PointF delta = m_velocity * elapsedTime; delta.y *= -1; // painter orientate Y axis in the inverse direction - PointF position = m_position + delta; + PointF position = m_pos + delta; - if(m_position != position) { + if(m_pos != position) { mustRedraw = true; - m_position += delta; + m_pos += delta; } // update acceleration m_velocity += m_acceleration * elapsedTime; } - m_rect.move((int)m_position.x - m_size.width() / 2, (int)m_position.y - m_size.height() / 2); + m_rect.move((int)m_pos.x - m_size.width() / 2, (int)m_pos.y - m_size.height() / 2); } void Particle::updateSize() diff --git a/src/framework/graphics/particle.h b/src/framework/graphics/particle.h index f7929785..692f4131 100644 --- a/src/framework/graphics/particle.h +++ b/src/framework/graphics/particle.h @@ -36,10 +36,10 @@ public: bool hasFinished() { return m_finished; } - PointF getPos() { return m_position; } + PointF getPos() { return m_pos; } PointF getVelocity() { return m_velocity; } - void setPos(const PointF& position) { m_position = position; } + void setPos(const PointF& position) { m_pos = position; } void setVelocity(const PointF& velocity) { m_velocity = velocity; } private: @@ -51,7 +51,7 @@ private: std::vector m_colors; std::vector m_colorsStops; TexturePtr m_texture; - PointF m_position; + PointF m_pos; PointF m_velocity; PointF m_acceleration; Size m_size, m_startSize, m_finalSize; diff --git a/src/framework/graphics/particleaffector.cpp b/src/framework/graphics/particleaffector.cpp index b818945a..1576ca67 100644 --- a/src/framework/graphics/particleaffector.cpp +++ b/src/framework/graphics/particleaffector.cpp @@ -115,7 +115,7 @@ bool AttractionAffector::load(const OTMLNodePtr& node) for(const OTMLNodePtr& childNode : node->children()) { if(childNode->tag() == "position") - m_position = childNode->value(); + m_pos = childNode->value(); else if(childNode->tag() == "acceleration") m_acceleration = childNode->value(); else if(childNode->tag() == "velocity-reduction-percent") @@ -132,7 +132,7 @@ void AttractionAffector::updateParticle(const ParticlePtr& particle, double elap return; PointF pPosition = particle->getPos(); - PointF d = PointF(m_position.x - pPosition.x, pPosition.y - m_position.y); + PointF d = PointF(m_pos.x - pPosition.x, pPosition.y - m_pos.y); if(d.length() == 0) return; diff --git a/src/framework/graphics/particleaffector.h b/src/framework/graphics/particleaffector.h index dbfd2f2c..3f72116f 100644 --- a/src/framework/graphics/particleaffector.h +++ b/src/framework/graphics/particleaffector.h @@ -57,7 +57,7 @@ public: void updateParticle(const ParticlePtr& particle, double elapsedTime); private: - Point m_position; + Point m_pos; float m_acceleration, m_reduction; bool m_repelish; }; diff --git a/src/framework/graphics/particleemitter.cpp b/src/framework/graphics/particleemitter.cpp index e7d808f7..50e92dd0 100644 --- a/src/framework/graphics/particleemitter.cpp +++ b/src/framework/graphics/particleemitter.cpp @@ -31,7 +31,7 @@ ParticleEmitter::ParticleEmitter(const ParticleSystemPtr& parent) { m_parent = parent; - m_position = Point(0, 0); + m_pos = Point(0, 0); m_duration = -1; m_delay = 0; m_burstRate = 1; m_burstCount = 32; @@ -65,7 +65,7 @@ bool ParticleEmitter::load(const OTMLNodePtr& node) for(const OTMLNodePtr& childNode : node->children()) { // self related if(childNode->tag() == "position") - m_position = childNode->value(); + m_pos = childNode->value(); else if(childNode->tag() == "duration") m_duration = childNode->value(); else if(childNode->tag() == "delay") @@ -199,7 +199,7 @@ void ParticleEmitter::update(double elapsedTime) float pRadius = Fw::randomRange(m_pMinPositionRadius, m_pMaxPositionRadius); float pAngle = Fw::randomRange(m_pMinPositionAngle, m_pMaxPositionAngle); - Point pPosition = m_position + Point(pRadius * cos(pAngle), pRadius * sin(pAngle)); + Point pPosition = m_pos + Point(pRadius * cos(pAngle), pRadius * sin(pAngle)); for(int p = 0; p < m_burstCount; ++p) { diff --git a/src/framework/graphics/particleemitter.h b/src/framework/graphics/particleemitter.h index 402a96e4..12e88ef0 100644 --- a/src/framework/graphics/particleemitter.h +++ b/src/framework/graphics/particleemitter.h @@ -44,7 +44,7 @@ private: ParticleSystemWeakPtr m_parent; // self related - Point m_position; + Point m_pos; float m_duration, m_delay; double m_elapsedTime; bool m_finished, m_active; diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index a9daa038..1fc593da 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -294,12 +294,12 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("setFitChildren", &UIBoxLayout::setFitChildren); // UIVerticalLayout - g_lua.registerClass(); + g_lua.registerClass(); g_lua.bindClassStaticFunction("create", [](UIWidgetPtr parent){ return UIVerticalLayoutPtr(new UIVerticalLayout(parent)); } ); g_lua.bindClassMemberFunction("setAlignBottom", &UIVerticalLayout::setAlignBottom); // UIHorizontalLayout - g_lua.registerClass(); + g_lua.registerClass(); g_lua.bindClassStaticFunction("create", [](UIWidgetPtr parent){ return UIHorizontalLayoutPtr(new UIHorizontalLayout(parent)); } ); g_lua.bindClassMemberFunction("setAlignRight", &UIHorizontalLayout::setAlignRight); @@ -404,6 +404,7 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("g_window", "getY", std::bind(&PlatformWindow::getY, &g_window)); g_lua.bindClassStaticFunction("g_window", "getMousePos", std::bind(&PlatformWindow::getMousePos, &g_window)); g_lua.bindClassStaticFunction("g_window", "getKeyboardModifiers", std::bind(&PlatformWindow::getKeyboardModifiers, &g_window)); + g_lua.bindClassStaticFunction("g_window", "isKeyPressed", std::bind(&PlatformWindow::isKeyPressed, &g_window, _1)); g_lua.bindClassStaticFunction("g_window", "isVisible", std::bind(&PlatformWindow::isVisible, &g_window)); g_lua.bindClassStaticFunction("g_window", "isFullscreen", std::bind(&PlatformWindow::isFullscreen, &g_window)); g_lua.bindClassStaticFunction("g_window", "isMaximized", std::bind(&PlatformWindow::isMaximized, &g_window)); diff --git a/src/framework/platform/platformwindow.cpp b/src/framework/platform/platformwindow.cpp index 88eff0af..8e9e4856 100644 --- a/src/framework/platform/platformwindow.cpp +++ b/src/framework/platform/platformwindow.cpp @@ -27,6 +27,7 @@ WIN32Window window; #else #include "x11window.h" +#include X11Window window; #endif @@ -39,3 +40,83 @@ void PlatformWindow::updateUnmaximizedCoords() m_unmaximizedSize = m_size; } } + +void PlatformWindow::processKeyDown(Fw::Key keyCode) +{ + if(keyCode == Fw::KeyUnknown || m_keysState[keyCode]) + return; + + m_keysState[keyCode] = true; + m_lastKeysPress[keyCode] = -1; + + if(keyCode == Fw::KeyCtrl) + m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier; + else if(keyCode == Fw::KeyAlt) + m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier; + else if(keyCode == Fw::KeyShift) + m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier; + + m_inputEvent.reset(); + m_inputEvent.type = Fw::KeyDownInputEvent; + m_inputEvent.keyCode = keyCode; + + if(m_onInputEvent) { + m_onInputEvent(m_inputEvent); + + m_inputEvent.reset(Fw::KeyPressInputEvent); + m_inputEvent.keyCode = keyCode; + m_lastKeysPress[keyCode] = g_clock.ticks(); + m_firstKeysPress[keyCode] = g_clock.ticks(); + m_onInputEvent(m_inputEvent); + } +} + +void PlatformWindow::processKeyRelease(Fw::Key keyCode) +{ + if(keyCode == Fw::KeyUnknown || !m_keysState[keyCode]) + return; + + m_keysState[keyCode] = false; + + if(keyCode == Fw::KeyCtrl) + m_inputEvent.keyboardModifiers &= ~Fw::KeyboardCtrlModifier; + else if(keyCode == Fw::KeyAlt) + m_inputEvent.keyboardModifiers &= ~Fw::KeyboardAltModifier; + else if(keyCode == Fw::KeyShift) + m_inputEvent.keyboardModifiers &= ~Fw::KeyboardShiftModifier; + + if(m_onInputEvent) { + m_inputEvent.reset(Fw::KeyReleaseInputEvent); + m_onInputEvent(m_inputEvent); + } +} + +void PlatformWindow::fireKeysPress() +{ + // avoid massive checks + if(m_keyPressTimer.ticksElapsed() < 10) + return; + m_keyPressTimer.restart(); + + for(auto it : m_keysState) { + Fw::Key keyCode = it.first; + bool pressed = it.second; + + if(!pressed) + continue; + + ticks_t lastPressTicks = m_lastKeysPress[keyCode]; + ticks_t firstKeyPress = m_firstKeysPress[keyCode]; + if(g_clock.ticksElapsed(lastPressTicks) >= KEY_PRESS_REPEAT_INTERVAL) { + if(m_onInputEvent) { + m_inputEvent.reset(); + m_inputEvent.type = Fw::KeyPressInputEvent; + m_inputEvent.keyCode = keyCode; + m_inputEvent.wouldFilter = g_clock.ticksElapsed(firstKeyPress) < KEY_PRESS_REPEAT_DELAY; + m_onInputEvent(m_inputEvent); + } + m_lastKeysPress[keyCode] = g_clock.ticks(); + } + } +} + diff --git a/src/framework/platform/platformwindow.h b/src/framework/platform/platformwindow.h index 020bcf11..0a53a04c 100644 --- a/src/framework/platform/platformwindow.h +++ b/src/framework/platform/platformwindow.h @@ -25,9 +25,15 @@ #include #include +#include class PlatformWindow { + enum { + KEY_PRESS_REPEAT_INTERVAL = 30, + KEY_PRESS_REPEAT_DELAY = 500 + }; + typedef std::function OnResizeCallback; typedef std::function OnInputEventCallback; @@ -72,6 +78,7 @@ public: int getY() { return m_pos.y; } Point getMousePos() { return m_inputEvent.mousePos; } int getKeyboardModifiers() { return m_inputEvent.keyboardModifiers; } + bool isKeyPressed(Fw::Key keyCode) { return m_keysState[keyCode]; } bool isVisible() { return m_visible; } bool isFullscreen() { return m_fullscreen; } @@ -85,6 +92,16 @@ public: protected: void updateUnmaximizedCoords(); + void processKeyDown(Fw::Key keyCode); + void processKeyRelease(Fw::Key keyCode); + void fireKeysPress(); + + std::map m_keyMap; + std::map> m_keysState; + std::map m_firstKeysPress; + std::map m_lastKeysPress; + Timer m_keyPressTimer; + Size m_size; Point m_pos; Size m_unmaximizedSize; diff --git a/src/framework/platform/win32window.cpp b/src/framework/platform/win32window.cpp index 1b081208..32bf3666 100644 --- a/src/framework/platform/win32window.cpp +++ b/src/framework/platform/win32window.cpp @@ -35,7 +35,6 @@ WIN32Window::WIN32Window() m_maximized = false; m_minimumSize = Size(16,16); m_size = m_minimumSize; - m_inputEvent.keyboardModifiers = 0; m_keyMap[VK_ESCAPE] = Fw::KeyEscape; m_keyMap[VK_TAB] = Fw::KeyTab; diff --git a/src/framework/platform/win32window.h b/src/framework/platform/win32window.h index 1389f5e6..df40f8c5 100644 --- a/src/framework/platform/win32window.h +++ b/src/framework/platform/win32window.h @@ -82,7 +82,6 @@ private: HGLRC m_glContext; bool m_maximized; Size m_minimumSize; - std::map m_keyMap; }; #endif diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index b8af7bb6..800cddcc 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -39,7 +39,6 @@ X11Window::X11Window() m_screen = 0; m_wmDelete = 0; m_size = Size(16,16); - m_inputEvent.keyboardModifiers = 0; #ifndef OPENGL_ES2 m_glxContext = 0; @@ -526,33 +525,41 @@ void X11Window::poll() while(XPending(m_display) > 0) { XNextEvent(m_display, &event); - // call filter because xim will discard KeyPress events when keys still composing - if(XFilterEvent(&event, m_window)) - continue; - - // discard events of repeated key releases + // check for repeated key releases + bool repatedKeyRelease = false; if(event.type == KeyRelease && XPending(m_display)) { XPeekEvent(m_display, &peekEvent); - if((peekEvent.type == KeyPress) && - (peekEvent.xkey.keycode == event.xkey.keycode) && - ((peekEvent.xkey.time-event.xkey.time) < 2)) - continue; + if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2)) + repatedKeyRelease = true; } - // reset inputEvent values, except keyboardModifiers and mousePos - m_inputEvent.type = Fw::NoInputEvent; - m_inputEvent.mouseButton = Fw::MouseNoButton; - m_inputEvent.keyCode = Fw::KeyUnknown; - m_inputEvent.keyText = ""; - m_inputEvent.mouseMoved = Point(); - m_inputEvent.wheelDirection = Fw::MouseNoWheel; - m_inputEvent.keyboardModifiers = 0; - if(event.xkey.state & ControlMask) - m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier; - if(event.xkey.state & ShiftMask) - m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier; - if(event.xkey.state & Mod1Mask) - m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier; + // process keydown and keyrelease events first + if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) { + // remove caps lock and shift maks + XKeyEvent xkey = event.xkey; + xkey.state &= ~(ShiftMask | LockMask); + + // lookup keysym and translate it + KeySym keysym; + char buf[32]; + int len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0); + Fw::Key keyCode = Fw::KeyUnknown; + if(m_keyMap.find(keysym) != m_keyMap.end()) + keyCode = m_keyMap[keysym]; + + if(event.type == KeyPress) + processKeyDown(keyCode); + else if(event.type == KeyRelease) + processKeyRelease(keyCode); + } + + // call filter because xim will discard KeyPress events when keys still composing + if(XFilterEvent(&event, m_window)) + continue; + + // discard repated key releases + if(repatedKeyRelease) + continue; switch(event.type) { case ClientMessage: { @@ -614,55 +621,44 @@ void X11Window::poll() XFlush(m_display); break; } - case KeyPress: - case KeyRelease: { + // process text events + case KeyPress: { + // text cant be insert while holding ctrl or alt + if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask) + break; + + // process key text events KeySym keysym; char buf[32]; memset(buf, 0, 32); int len; // lookup for keyText - if(event.type == KeyPress && !(event.xkey.state & ControlMask) && !(event.xkey.state & Mod1Mask)) { - if(m_xic) { // with xim we can get latin1 input correctly - Status status; - len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status); - } else { // otherwise use XLookupString, but often it doesn't work right with dead keys - static XComposeStatus compose = {NULL, 0}; - len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose); - } - - if(len > 0 && - // these keys produces characters that we don't want to capture - keysym != XK_BackSpace && - keysym != XK_Return && - keysym != XK_Delete && - keysym != XK_Escape && - (uchar)(buf[0]) >= 32 - ) { - //logDebug("char: ", buf[0], " code: ", (uint)buf[0]); - m_inputEvent.keyText = buf; - } + if(m_xic) { // with xim we can get latin1 input correctly + Status status; + len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status); + } else { // otherwise use XLookupString, but often it doesn't work right with dead keys + static XComposeStatus compose = {NULL, 0}; + len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose); } - XKeyEvent xkey = event.xkey; - xkey.state = xkey.state & ~(ShiftMask); - len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0); - if(len > 0 && m_inputEvent.keyText.length() == 0 && keysym != XK_BackSpace && - keysym != XK_Return && - keysym != XK_Delete && - keysym != XK_Escape) - m_inputEvent.keyText = buf; + // filter unwanted characters + if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape) + break; + std::string text = buf; - if(m_keyMap.find(keysym) != m_keyMap.end()) - m_inputEvent.keyCode = m_keyMap[keysym]; + //logDebug("char: ", buf[0], " code: ", (int)((uchar)buf[0])); - m_inputEvent.type = (event.type == KeyPress) ? Fw::KeyPressInputEvent : Fw::KeyReleaseInputEvent; - if(m_inputEvent.keyCode != Fw::KeyUnknown || !m_inputEvent.keyText.empty()) + if(m_onInputEvent && text.length() > 0) { + m_inputEvent.reset(Fw::KeyTextInputEvent); + m_inputEvent.keyText = text; m_onInputEvent(m_inputEvent); + } break; } case ButtonPress: case ButtonRelease: { + m_inputEvent.reset(); m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent; switch(event.xbutton.button) { case Button1: @@ -694,6 +690,7 @@ void X11Window::poll() } case MotionNotify: { + m_inputEvent.reset(); m_inputEvent.type = Fw::MouseMoveInputEvent; Point newMousePos(event.xbutton.x, event.xbutton.y); m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos; @@ -722,6 +719,8 @@ void X11Window::poll() if(needsResizeUpdate && m_onResize) m_onResize(m_size); + + fireKeysPress(); } void X11Window::swapBuffers() diff --git a/src/framework/platform/x11window.h b/src/framework/platform/x11window.h index 175b43a4..8253976d 100644 --- a/src/framework/platform/x11window.h +++ b/src/framework/platform/x11window.h @@ -93,7 +93,6 @@ private: int m_screen; Atom m_wmDelete; std::string m_clipboardText; - std::map m_keyMap; #ifndef OPENGL_ES2 GLXContext m_glxContext; diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 40149114..37e6ae7c 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -389,6 +389,8 @@ void UILineEdit::onStyleApply(const std::string& styleName, const OTMLNodePtr& s setTextHorizontalMargin(node->value()); else if(node->tag() == "always-active") setAlwaysActive(node->value()); + //else if(node->tag() == "disable-arrow-navitation") + // setArrowNavigation(node->value()); } } @@ -409,34 +411,41 @@ void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason) UIWidget::onFocusChange(focused, reason); } -bool UILineEdit::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UILineEdit::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter) { - if(UIWidget::onKeyPress(keyCode, keyText, keyboardModifiers)) + if(UIWidget::onKeyPress(keyCode, keyboardModifiers, wouldFilter)) return true; - if(keyCode == Fw::KeyDelete) // erase right character - removeCharacter(true); - else if(keyCode == Fw::KeyBackspace) // erase left character { - removeCharacter(false); - else if(keyCode == Fw::KeyRight) // move cursor right - moveCursor(true); - else if(keyCode == Fw::KeyLeft) // move cursor left - moveCursor(false); - else if(keyCode == Fw::KeyHome) // move cursor to first character - setCursorPos(0); - else if(keyCode == Fw::KeyEnd) // move cursor to last character - setCursorPos(m_text.length()); - else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier) - appendText(g_window.getClipboardText()); - else if(keyCode == Fw::KeyTab) { - if(!m_alwaysActive) { - if(UIWidgetPtr parent = getParent()) - parent->focusNextChild(Fw::TabFocusReason); - } - } else if(!keyText.empty() && (keyboardModifiers == Fw::KeyboardNoModifier || keyboardModifiers == Fw::KeyboardShiftModifier)) - appendText(keyText); - else - return false; + if(!wouldFilter) { + if(keyCode == Fw::KeyDelete) // erase right character + removeCharacter(true); + else if(keyCode == Fw::KeyBackspace) // erase left character { + removeCharacter(false); + else if(keyCode == Fw::KeyRight) // move cursor right + moveCursor(true); + else if(keyCode == Fw::KeyLeft) // move cursor left + moveCursor(false); + else if(keyCode == Fw::KeyHome) // move cursor to first character + setCursorPos(0); + else if(keyCode == Fw::KeyEnd) // move cursor to last character + setCursorPos(m_text.length()); + else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier) + appendText(g_window.getClipboardText()); + else if(keyCode == Fw::KeyTab) { + if(!m_alwaysActive) { + if(UIWidgetPtr parent = getParent()) + parent->focusNextChild(Fw::TabFocusReason); + } + } else + return false; + return true; + } + return false; +} + +bool UILineEdit::onKeyText(const std::string& keyText) +{ + appendText(keyText); return true; } diff --git a/src/framework/ui/uilineedit.h b/src/framework/ui/uilineedit.h index 1cb73d7f..e65cfda2 100644 --- a/src/framework/ui/uilineedit.h +++ b/src/framework/ui/uilineedit.h @@ -61,7 +61,8 @@ protected: virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode); virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect); virtual void onFocusChange(bool focused, Fw::FocusReason reason); - virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers); + virtual bool onKeyText(const std::string& keyText); + virtual bool onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter); virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button); private: diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index 5245a919..f2983f7c 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -59,11 +59,17 @@ void UIManager::inputEvent(const InputEvent& event) { m_isOnInputEvent = true; switch(event.type) { + case Fw::KeyTextInputEvent: + m_keyboardReceiver->propagateOnKeyText(event.keyText); + break; + case Fw::KeyDownInputEvent: + m_keyboardReceiver->propagateOnKeyDown(event.keyCode, event.keyboardModifiers); + break; case Fw::KeyPressInputEvent: - m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyText, event.keyboardModifiers); + m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyboardModifiers, event.wouldFilter); break; case Fw::KeyReleaseInputEvent: - m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers); + m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyboardModifiers); break; case Fw::MousePressInputEvent: m_keyboardReceiver->propagateOnMousePress(event.mousePos, event.mouseButton); diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index b089ec93..1be66b7f 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -1053,14 +1053,24 @@ void UIWidget::onHoverChange(bool hovered) g_ui.getRootWidget()->updateState(Fw::HoverState); } -bool UIWidget::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UIWidget::onKeyText(const std::string& keyText) { - return callLuaField("onKeyPress", keyCode, keyText, keyboardModifiers); + return callLuaField("onKeyText", keyText); } -bool UIWidget::onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UIWidget::onKeyDown(uchar keyCode, int keyboardModifiers) { - return callLuaField("onKeyRelease", keyCode, keyText, keyboardModifiers); + return callLuaField("onKeyDown", keyCode, keyboardModifiers); +} + +bool UIWidget::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter) +{ + return callLuaField("onKeyPress", keyCode, keyboardModifiers, wouldFilter); +} + +bool UIWidget::onKeyRelease(uchar keyCode, int keyboardModifiers) +{ + return callLuaField("onKeyRelease", keyCode, keyboardModifiers); } bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button) @@ -1086,7 +1096,51 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc return callLuaField("onMouseWheel", mousePos, direction); } -bool UIWidget::propagateOnKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UIWidget::propagateOnKeyText(const std::string& keyText) +{ + // do a backup of children list, because it may change while looping it + UIWidgetList children; + for(const UIWidgetPtr& child : m_children) { + // events on hidden or disabled widgets are discarded + if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) + continue; + + // key events go only to containers or focused child + if(child->isFocused()) + children.push_back(child); + } + + for(const UIWidgetPtr& child : children) { + if(child->propagateOnKeyText(keyText)) + return true; + } + + return onKeyText(keyText); +} + +bool UIWidget::propagateOnKeyDown(uchar keyCode, int keyboardModifiers) +{ + // do a backup of children list, because it may change while looping it + UIWidgetList children; + for(const UIWidgetPtr& child : m_children) { + // events on hidden or disabled widgets are discarded + if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) + continue; + + // key events go only to containers or focused child + if(child->isFocused()) + children.push_back(child); + } + + for(const UIWidgetPtr& child : children) { + if(child->propagateOnKeyDown(keyCode, keyboardModifiers)) + return true; + } + + return onKeyDown(keyCode, keyboardModifiers); +} + +bool UIWidget::propagateOnKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter) { // do a backup of children list, because it may change while looping it UIWidgetList children; @@ -1101,14 +1155,14 @@ bool UIWidget::propagateOnKeyPress(uchar keyCode, std::string keyText, int keybo } for(const UIWidgetPtr& child : children) { - if(child->propagateOnKeyPress(keyCode, keyText, keyboardModifiers)) + if(child->propagateOnKeyPress(keyCode, keyboardModifiers, wouldFilter)) return true; } - return onKeyPress(keyCode, keyText, keyboardModifiers); + return onKeyPress(keyCode, keyboardModifiers, wouldFilter); } -bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UIWidget::propagateOnKeyRelease(uchar keyCode, int keyboardModifiers) { // do a backup of children list, because it may change while looping it UIWidgetList children; @@ -1123,11 +1177,11 @@ bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int key } for(const UIWidgetPtr& child : children) { - if(child->propagateOnKeyRelease(keyCode, keyText, keyboardModifiers)) + if(child->propagateOnKeyRelease(keyCode, keyboardModifiers)) return true; } - return onKeyRelease(keyCode, keyText, keyboardModifiers); + return onKeyRelease(keyCode, keyboardModifiers); } bool UIWidget::propagateOnMousePress(const Point& mousePos, Fw::MouseButton button) diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 1b094a81..192b2db8 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -161,15 +161,19 @@ protected: virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect); virtual void onFocusChange(bool focused, Fw::FocusReason reason); virtual void onHoverChange(bool hovered); - virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers); - virtual bool onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers); + virtual bool onKeyText(const std::string& keyText); + virtual bool onKeyDown(uchar keyCode, int keyboardModifiers); + virtual bool onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter); + virtual bool onKeyRelease(uchar keyCode, int keyboardModifiers); virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button); virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved); virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction); - bool propagateOnKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers); - bool propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers); + bool propagateOnKeyText(const std::string& keyText); + bool propagateOnKeyDown(uchar keyCode, int keyboardModifiers); + bool propagateOnKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter); + bool propagateOnKeyRelease(uchar keyCode, int keyboardModifiers); bool propagateOnMousePress(const Point& mousePos, Fw::MouseButton button); void propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton button); bool propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved); diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index e056f266..be678c95 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -47,7 +47,7 @@ Creature::Creature() : Thing() m_walkTimePerPixel = 1000.0/32.0; m_walking = false; - m_inverseWalking = true; + m_preWalking = false; m_skull = Otc::SkullNone; m_shield = Otc::ShieldNone; @@ -189,51 +189,44 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& visibleRe } } -void Creature::walk(const Position& position, bool inverse) +void Creature::walk(const Position& oldPos, const Position& newPos, bool preWalk) { - // We're walking - if(m_position.isInRange(position, 1, 1, 0)) { - Otc::Direction direction = m_position.getDirectionFromPosition(position); - setDirection(direction); - - if(inverse) { - Position positionDelta = m_position - position; - m_walkOffset = Point(positionDelta.x * Map::NUM_TILE_PIXELS, positionDelta.y * Map::NUM_TILE_PIXELS); - } - else - m_walkOffset = Point(0, 0); + // get walk direction + Otc::Direction direction = oldPos.getDirectionFromPosition(newPos); - // Diagonal walking lasts 3 times more. - int walkTimeFactor = 1; - if(direction == Otc::NorthWest || direction == Otc::NorthEast || direction == Otc::SouthWest || direction == Otc::SouthEast) - walkTimeFactor = 3; - - // Get walking speed - int groundSpeed = 100; - if(ItemPtr ground = g_map.getTile(position)->getGround()) - groundSpeed = ground->getType()->parameters[ThingType::GroundSpeed]; - - float walkTime = 1000.0 * (float)groundSpeed / m_speed; - walkTime = (walkTime == 0) ? 1000 : walkTime; - walkTime = std::ceil(walkTime / g_game.getServerBeat()) * g_game.getServerBeat(); + // already pre walking to the same direction + if(m_preWalking && preWalk && direction == m_direction) + return; - bool sameWalk = m_walking && !m_inverseWalking && inverse; - m_inverseWalking = inverse; + // pre walking was already going on, just change to normal waking + if(m_preWalking && !preWalk && direction == m_direction) { + m_preWalking = false; m_walking = true; - - m_walkTimePerPixel = walkTime / 32.0; - m_walkStart = sameWalk ? m_walkStart : g_clock.ticks(); - m_walkEnd = m_walkStart + walkTime * walkTimeFactor; - - m_turnDirection = m_direction; updateWalk(); + return; } - // Teleport - else { - m_walking = false; - m_walkOffset = Point(0, 0); - m_animation = 0; - } + + setDirection(direction); + + // diagonal walking lasts 3 times more. + int walkTimeFactor = 1; + if(direction == Otc::NorthWest || direction == Otc::NorthEast || direction == Otc::SouthWest || direction == Otc::SouthEast) + walkTimeFactor = 3; + + // calculate walk interval + int groundSpeed = g_map.getTile(oldPos)->getGroundSpeed(); + float walkInterval = 1000.0 * (float)groundSpeed / m_speed; + walkInterval = (walkInterval == 0) ? 1000 : walkInterval; + walkInterval = std::ceil(walkInterval / g_game.getServerBeat()) * g_game.getServerBeat(); + + m_walkTimePerPixel = walkInterval / 32.0; + m_walkOffset = Point(); + m_walkStart = g_clock.ticks(); + m_walkEnd = m_walkStart + walkInterval * walkTimeFactor; + m_walking = true; + m_preWalking = preWalk; + m_turnDirection = m_direction; + updateWalk(); } void Creature::turn(Otc::Direction direction) @@ -252,7 +245,7 @@ void Creature::updateWalk() int elapsedTicks = g_clock.ticksElapsed(m_walkStart); int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32); - if(m_inverseWalking) { + if(!m_preWalking) { if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest) m_walkOffset.y = 32 - totalPixelsWalked; else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest) @@ -262,8 +255,7 @@ void Creature::updateWalk() m_walkOffset.x = totalPixelsWalked - 32; else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest) m_walkOffset.x = 32 - totalPixelsWalked; - } - else { + } else { if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest) m_walkOffset.y = -totalPixelsWalked; else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest) @@ -282,20 +274,26 @@ void Creature::updateWalk() m_animation = 1 + totalPixelsWalked * 4 / Map::NUM_TILE_PIXELS % (m_type->dimensions[ThingType::AnimationPhases] - 1); } - if(g_clock.ticks() > m_walkEnd) + if(g_clock.ticks() > m_walkEnd) { cancelWalk(m_turnDirection); - else + } else g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel); } -void Creature::cancelWalk(Otc::Direction direction, bool) +void Creature::cancelWalk(Otc::Direction direction, bool force) { + if(force) { + m_walkOffset = Point(); + m_preWalking = false; + } else if(!m_preWalking) + m_walkOffset = Point(); m_walking = false; - m_walkStart = 0; + + if(direction != Otc::InvalidDirection) + setDirection(direction); + if(m_outfit.getCategory() == ThingsType::Creature) m_animation = 0; - m_walkOffset = Point(0, 0); - setDirection(direction); } void Creature::setName(const std::string& name) @@ -345,8 +343,7 @@ void Creature::setDirection(Otc::Direction direction) m_xPattern = Otc::West; else m_xPattern = direction; - } - else { + } else { m_xPattern = 0; } @@ -358,7 +355,7 @@ void Creature::setOutfit(const Outfit& outfit) if(m_outfit.getCategory() != ThingsType::Effect && outfit.getCategory() == ThingsType::Effect) { auto self = asCreature(); g_dispatcher.scheduleEvent([self]() { - self->updateAnimation(); + self->updateInvisibleAnimation(); }, INVISIBLE_TICKS); m_xPattern = 0; @@ -433,7 +430,7 @@ void Creature::addVolatileSquare(uint8 color) }, VOLATILE_SQUARE_DURATION); } -void Creature::updateAnimation() +void Creature::updateInvisibleAnimation() { if(m_animation == 1) m_animation = 2; @@ -447,7 +444,7 @@ void Creature::updateAnimation() if(g_game.isOnline() && m_outfit.getCategory() == ThingsType::Effect) { auto self = asCreature(); g_dispatcher.scheduleEvent([self]() { - self->updateAnimation(); + self->updateInvisibleAnimation(); }, INVISIBLE_TICKS); } } @@ -470,3 +467,4 @@ ThingType *Creature::getType() { return g_thingsType.getThingType(m_outfit.getId(), m_outfit.getCategory()); } + diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index cf6e958c..bdaff1c4 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -73,18 +73,19 @@ public: uint8 getEmblem() { return m_emblem; } bool getPassable() { return m_passable; } - void updateAnimation(); + void updateInvisibleAnimation(); void updateShield(); ThingType *getType(); - //virtual void walk(const Position& oldPos, const Position& newPos, bool inverse = true); - virtual void walk(const Position& position, bool inverse = true); + // walk related + void walk(const Position& oldPos, const Position& newPos, bool preWalk = false); void turn(Otc::Direction direction); - virtual void cancelWalk(Otc::Direction direction, bool force = false); + void cancelWalk(Otc::Direction direction = Otc::InvalidDirection, bool force = false); Point getWalkOffset() { return m_walkOffset; } bool isWalking() { return m_walking; } + bool isPreWalking() { return m_preWalking; } CreaturePtr asCreature() { return std::static_pointer_cast(shared_from_this()); } @@ -109,7 +110,7 @@ protected: Color m_informationColor; ticks_t m_walkStart, m_walkEnd; - bool m_walking, m_inverseWalking; + bool m_walking, m_preWalking; float m_walkTimePerPixel; Point m_walkOffset; Otc::Direction m_turnDirection; diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 20f2a2d0..e24c3c3c 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -140,23 +140,22 @@ void Game::processInventoryChange(int slot, const ItemPtr& item) void Game::processCreatureMove(const CreaturePtr& creature, const Position& oldPos, const Position& newPos) { - /* // walk if(oldPos.isInRange(newPos, 1, 1, 0)) { - Otc::Direction direction = oldPos.getDirectionFromPosition(newPos); - creature->setDirection(direction); + creature->walk(oldPos, newPos); // teleport } else { - // stop animation on teleport + // stop walking on teleport if(creature->isWalking()) creature->cancelWalk(); } - */ - if(!m_walkFeedback && creature == m_localPlayer) { - updateWalkPing(); - m_walkFeedback = true; + + if(creature == m_localPlayer) { + if(!m_walkFeedback) { + updateWalkPing(); + m_walkFeedback = true; + } } - creature->walk(newPos); } void Game::processAttackCancel() @@ -176,18 +175,23 @@ void Game::processWalkCancel(Otc::Direction direction) void Game::walk(Otc::Direction direction) { - if(m_localPlayer->isFollowing()) { - cancelFollow(); + if(!isOnline() || isDead() || !checkBotProtection()) return; - } - if(!isOnline() || isDead() || !checkBotProtection() || !m_localPlayer->canWalk(direction)) + if(m_localPlayer->isFollowing()) + cancelFollow(); + + if(!m_localPlayer->canWalk(direction)) return; - m_localPlayer->clientWalk(direction); + m_localPlayer->preWalk(direction); + forceWalk(direction); +} - // ping calculation restarts when the local players try to walk one tile +void Game::forceWalk(Otc::Direction direction) +{ m_walkPingTimer.restart(); + m_walkFeedback = false; switch(direction) { case Otc::North: @@ -215,8 +219,6 @@ void Game::walk(Otc::Direction direction) m_protocolGame->sendWalkNorthWest(); break; } - - m_walkFeedback = false; } void Game::turn(Otc::Direction direction) @@ -334,6 +336,7 @@ void Game::rotate(const ThingPtr& thing) m_protocolGame->sendRotateItem(thing->getPos(), thing->getId(), stackpos); } +//TODO: move this to Thing class int Game::getThingStackpos(const ThingPtr& thing) { // thing is at map diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 466802cd..bcd6a34f 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -56,6 +56,7 @@ public: // walk related void walk(Otc::Direction direction); + void forceWalk(Otc::Direction direction); void turn(Otc::Direction direction); // item related diff --git a/src/otclient/core/localplayer.cpp b/src/otclient/core/localplayer.cpp index 4c7723f2..23313ddb 100644 --- a/src/otclient/core/localplayer.cpp +++ b/src/otclient/core/localplayer.cpp @@ -25,79 +25,20 @@ #include "game.h" #include "tile.h" -LocalPlayer::LocalPlayer() +void LocalPlayer::preWalk(Otc::Direction direction) { - m_clientWalking = false; - m_nextWalkDirection = Otc::InvalidDirection; -} - -void LocalPlayer::clientWalk(Otc::Direction direction) -{ - // We're not walking, so start a client walk. - assert(!m_walking); - Position newPos = m_position + Position::getPosFromDirection(direction); - Creature::walk(newPos, false); - m_clientWalking = true; -} - -void LocalPlayer::walk(const Position& position, bool inverse) -{ - // This can only be received by protocol, so its always inverse. - - // If we're already walking, just finish it. - if(m_clientWalking) { - m_clientWalking = false; - - Position pos = Position::getPosFromDirection(m_direction); - Point walkOffset = Point(m_walkOffset.x - pos.x * 32, - m_walkOffset.y - pos.y * 32); - - Creature::walk(position, inverse); - - // Restore walk offset, because we were already walking. - m_walkOffset = walkOffset; - } - // If we're not client walking, we'll just walk like every NPC. Ie: When player is pushed. - else - Creature::walk(position, inverse); -} - -void LocalPlayer::cancelWalk(Otc::Direction direction, bool force) -{ - // Server said we cant walk. Ie: houses, vip areas. - if(force) { - m_clientWalking = false; - Creature::cancelWalk(direction); - } - else { - // Walk finished, and we already received the confirmation from server. - if(m_walking && !m_clientWalking) { - m_clientWalking = false; - Creature::cancelWalk(direction); - - if(m_nextWalkDirection != Otc::InvalidDirection) { - g_game.walk(m_nextWalkDirection); - m_nextWalkDirection = Otc::InvalidDirection; - } - } - //else.. - // Walk finished, however we havent received the confirmation from server. So wait for it. - } + // we're not walking, so start a client walk. + Position newPos = m_pos + Position::getPosFromDirection(direction); + walk(m_pos, newPos, true); } bool LocalPlayer::canWalk(Otc::Direction direction) { - if(m_walking) { - if(direction != m_direction && m_nextWalkDirection != direction) - m_nextWalkDirection = direction; - else if(direction == m_direction && m_nextWalkDirection != Otc::InvalidDirection) - m_nextWalkDirection = Otc::InvalidDirection; - + if(m_walking || (m_preWalking && g_clock.ticksElapsed(m_walkEnd) < 1000)) return false; - } - Position newPos = m_position + Position::getPosFromDirection(direction); - TilePtr tile = g_map.getTile(newPos); + // check for blockable tiles in the walk direction + TilePtr tile = g_map.getTile(m_pos + Position::getPosFromDirection(direction)); if(!tile->isWalkable()) { g_game.processTextMessage("statusSmall", "Sorry, not possible."); return false; @@ -108,11 +49,13 @@ bool LocalPlayer::canWalk(Otc::Direction direction) void LocalPlayer::setAttackingCreature(const CreaturePtr& creature) { + // clear current attacking creature if(m_attackingCreature) { m_attackingCreature->hideStaticSquare(); m_attackingCreature = nullptr; } + // set the new attacking creature if(creature) { creature->showStaticSquare(Fw::red); m_attackingCreature = creature; @@ -121,11 +64,13 @@ void LocalPlayer::setAttackingCreature(const CreaturePtr& creature) void LocalPlayer::setFollowingCreature(const CreaturePtr& creature) { + // clear current following creature if(m_followingCreature) { m_followingCreature->hideStaticSquare(); m_followingCreature = nullptr; } + // set the new attacking creature if(creature) { creature->showStaticSquare(Fw::green); m_followingCreature = creature; diff --git a/src/otclient/core/localplayer.h b/src/otclient/core/localplayer.h index a180d67f..39d80525 100644 --- a/src/otclient/core/localplayer.h +++ b/src/otclient/core/localplayer.h @@ -28,8 +28,6 @@ class LocalPlayer : public Player { public: - LocalPlayer(); - void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); } void setSkill(Otc::Skill skill, Otc::SkillType skillType, int value) { m_skills[skill][skillType] = value; } void setStatistic(Otc::Statistic statistic, double value) { m_statistics[statistic] = value; } @@ -42,25 +40,21 @@ public: double getStatistic(Otc::Statistic statistic) { return m_statistics[statistic]; } CreaturePtr getAttackingCreature() { return m_attackingCreature; } CreaturePtr getFollowingCreature() { return m_followingCreature; } - Otc::Direction getNextWalkDirection() { return m_nextWalkDirection; } Otc::PlayerIcons getIcons() { return m_icons; } bool isAttacking() { return m_attackingCreature != nullptr; } bool isFollowing() { return m_followingCreature != nullptr; } - void clientWalk(Otc::Direction direction); - void walk(const Position& position, bool inverse); - void cancelWalk(Otc::Direction direction, bool force = false); + void preWalk(Otc::Direction direction); bool canWalk(Otc::Direction direction); LocalPlayerPtr asLocalPlayer() { return std::static_pointer_cast(shared_from_this()); } double getLevel() { return getStatistic(Otc::Level); } + //TODO: more gets private: bool m_canReportBugs; - bool m_clientWalking; - Otc::Direction m_nextWalkDirection; CreaturePtr m_attackingCreature, m_followingCreature; Otc::PlayerIcons m_icons; int m_skills[Otc::LastSkill][Otc::LastSkillType]; diff --git a/src/otclient/core/missile.cpp b/src/otclient/core/missile.cpp index 70788f27..d765050f 100644 --- a/src/otclient/core/missile.cpp +++ b/src/otclient/core/missile.cpp @@ -35,7 +35,7 @@ Missile::Missile() : Thing() void Missile::draw(const Point& p, const Rect&) { float time = (g_clock.ticks() - m_startTicks) / m_duration; - internalDraw(p + Point(m_positionDelta.x * time, m_positionDelta.y * time), 0); + internalDraw(p + Point(m_posDelta.x * time, m_posDelta.y * time), 0); } void Missile::setPath(const Position& fromPosition, const Position& toPosition) @@ -79,12 +79,12 @@ void Missile::setPath(const Position& fromPosition, const Position& toPosition) m_yPattern = 1; } - m_position = fromPosition; - m_positionDelta = toPosition - fromPosition; + m_pos = fromPosition; + m_posDelta = toPosition - fromPosition; m_startTicks = g_clock.ticks(); - m_duration = 150 * std::sqrt(Point(m_positionDelta.x, m_positionDelta.y).length()); - m_positionDelta.x *= Map::NUM_TILE_PIXELS; - m_positionDelta.y *= Map::NUM_TILE_PIXELS; + m_duration = 150 * std::sqrt(Point(m_posDelta.x, m_posDelta.y).length()); + m_posDelta.x *= Map::NUM_TILE_PIXELS; + m_posDelta.y *= Map::NUM_TILE_PIXELS; // schedule removal auto self = asMissile(); diff --git a/src/otclient/core/missile.h b/src/otclient/core/missile.h index 1cd67e40..331b3cc3 100644 --- a/src/otclient/core/missile.h +++ b/src/otclient/core/missile.h @@ -47,7 +47,7 @@ public: private: ticks_t m_startTicks; - Position m_positionDelta; + Position m_posDelta; float m_duration; }; diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 0a86c0f1..6c83e6d3 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -44,13 +44,14 @@ public: virtual void draw(const Point& p, const Rect&) = 0; void setId(uint32 id); - virtual void setPos(const Position& position) { m_position = position; } + virtual void setPos(const Position& position) { m_pos = position; } uint32 getId() const { return m_id; } - Position getPos() const { return m_position; } + Position getPos() const { return m_pos; } int getStackPriority(); virtual ThingType *getType(); int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; } + int getGroundSpeed() { return m_type->parameters[ThingType::GroundSpeed]; } void setXPattern(int xPattern) { m_xPattern = xPattern; } void setYPattern(int yPattern) { m_yPattern = yPattern; } @@ -87,7 +88,7 @@ protected: void internalDraw(const Point& p, int layer); uint32 m_id; - Position m_position; + Position m_pos; ThingType *m_type; int m_xPattern, m_yPattern, m_zPattern, m_animation; diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 74f6ba81..5cdd6c64 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -33,7 +33,7 @@ Tile::Tile(const Position& position) { m_drawElevation = 0; - m_position = position; + m_pos = position; } void Tile::draw(const Point& p, const Rect& visibleRect) @@ -67,7 +67,7 @@ void Tile::draw(const Point& p, const Rect& visibleRect) //TODO: this algorithm is slowing down render too much, but it could be cached to improve framerate for(int xi = -1; xi <= 1; ++xi) { for(int yi = -1; yi <= 1; ++yi) { - for(CreaturePtr creature : g_map.getTile(m_position + Position(xi, yi, 0))->getCreatures()) { + for(CreaturePtr creature : g_map.getTile(m_pos + Position(xi, yi, 0))->getCreatures()) { ThingType *type = creature->getType(); Rect creatureRect(p.x + xi*32 + creature->getWalkOffset().x - type->parameters[ThingType::DisplacementX], p.y + yi*32 + creature->getWalkOffset().y - type->parameters[ThingType::DisplacementY], 32, 32); Rect thisTileRect(p.x, p.y, 32, 32); @@ -197,6 +197,14 @@ ItemPtr Tile::getGround() return nullptr; } +int Tile::getGroundSpeed() +{ + int groundSpeed = 100; + if(ItemPtr ground = getGround()) + groundSpeed = ground->getGroundSpeed(); + return groundSpeed; +} + ThingPtr Tile::getTopLookThing() { if(isEmpty()) diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 9b8fda95..c8a478a0 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -50,10 +50,11 @@ public: CreaturePtr getTopCreature(); ThingPtr getTopMultiUseThing(); - const Position& getPos() { return m_position; } + const Position& getPos() { return m_pos; } int getDrawElevation() { return m_drawElevation; } std::vector getCreatures(); ItemPtr getGround(); + int getGroundSpeed(); bool isWalkable(); bool isFullGround(); bool isFullyOpaque(); @@ -67,7 +68,7 @@ public: private: std::vector m_effects; // Leave this outside m_things because it has no stackpos. std::vector m_things; - Position m_position; + Position m_pos; int m_drawElevation; }; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 8bb4a132..d8ad7f84 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -186,6 +186,8 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("open", std::bind(&Game::open, &g_game, _1, _2)); g_lua.bindClassStaticFunction("use", std::bind(&Game::use, &g_game, _1)); g_lua.bindClassStaticFunction("useWith", std::bind(&Game::useWith, &g_game, _1, _2)); + g_lua.bindClassStaticFunction("walk", std::bind(&Game::walk, &g_game, _1)); + g_lua.bindClassStaticFunction("forceWalk", std::bind(&Game::forceWalk, &g_game, _1)); g_lua.bindClassStaticFunction("attack", std::bind(&Game::attack, &g_game, _1)); g_lua.bindClassStaticFunction("cancelAttack", std::bind(&Game::cancelAttack, &g_game)); g_lua.bindClassStaticFunction("follow", std::bind(&Game::follow, &g_game, _1)); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index cdda9b97..3cb1fddb 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -419,13 +419,11 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg) return; } - g_game.processCreatureMove(creature, oldPos, newPos); - // update map tiles g_map.removeThing(thing); g_map.addThing(thing, newPos); - //g_game.processCreatureMove(creature, oldPos, newPos); + g_game.processCreatureMove(creature, oldPos, newPos); } void ProtocolGame::parseOpenContainer(InputMessage& msg) diff --git a/src/otclient/ui/uigame.cpp b/src/otclient/ui/uigame.cpp index cbabd322..676db3e9 100644 --- a/src/otclient/ui/uigame.cpp +++ b/src/otclient/ui/uigame.cpp @@ -25,9 +25,9 @@ #include #include -bool UIGame::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers) +bool UIGame::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter) { - if(UIWidget::onKeyPress(keyCode, keyText, keyboardModifiers)) + if(UIWidget::onKeyPress(keyCode, keyboardModifiers, wouldFilter)) return true; UILineEditPtr chatLineEdit = std::dynamic_pointer_cast(getParent()->recursiveGetChildById("consoleLineEdit")); @@ -106,10 +106,15 @@ bool UIGame::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifier } } - if(!keyText.empty() && (keyboardModifiers == Fw::KeyboardNoModifier || keyboardModifiers == Fw::KeyboardShiftModifier)) { - chatLineEdit->appendText(keyText); + return false; +} + +bool UIGame::onKeyText(const std::string& keyText) +{ + if(UIWidget::onKeyText(keyText)) return true; - } - return false; + UILineEditPtr chatLineEdit = std::dynamic_pointer_cast(getParent()->recursiveGetChildById("consoleLineEdit")); + chatLineEdit->appendText(keyText); + return true; } diff --git a/src/otclient/ui/uigame.h b/src/otclient/ui/uigame.h index 4a198f80..df93d92a 100644 --- a/src/otclient/ui/uigame.h +++ b/src/otclient/ui/uigame.h @@ -29,8 +29,8 @@ class UIGame : public UIWidget { protected: - virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers); - + bool onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter); + bool onKeyText(const std::string& keyText); }; #endif diff --git a/src/otclient/util/position.h b/src/otclient/util/position.h index 45ef871f..bcbdd50d 100644 --- a/src/otclient/util/position.h +++ b/src/otclient/util/position.h @@ -109,7 +109,7 @@ public: bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; } bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; } - bool isInRange(const Position& pos, int xdif, int ydif, int zdif = 1) { + bool isInRange(const Position& pos, int xdif, int ydif, int zdif = 1) const { return std::abs(x-pos.x) <= xdif && std::abs(y-pos.y) <= ydif && std::abs(pos.z-z) <= zdif; }