walk and key event system rework with some regressions
This commit is contained in:
parent
9ec40f016d
commit
44a20222bb
6
TODO
6
TODO
|
@ -1,7 +1,6 @@
|
||||||
====================================================
|
====================================================
|
||||||
High priority TODO in order (before first public disclose)
|
High priority TODO in order (before first public disclose)
|
||||||
|
|
||||||
[bart] tab widgets
|
|
||||||
[bart] chat with tabs
|
[bart] chat with tabs
|
||||||
[bart] scrollbar
|
[bart] scrollbar
|
||||||
[bart] scrollable widgets
|
[bart] scrollable widgets
|
||||||
|
@ -62,8 +61,10 @@ change win32 mouse cursor icon
|
||||||
[bart] review and make more error prone with more warnings
|
[bart] review and make more error prone with more warnings
|
||||||
[bart] reapply anchor styles when adding new childs
|
[bart] reapply anchor styles when adding new childs
|
||||||
[bart] ui text selection
|
[bart] ui text selection
|
||||||
|
[bart] find styles by scope
|
||||||
[bart] make set of background/icon/image width alone work
|
[bart] make set of background/icon/image width alone work
|
||||||
[bart] check for recursive anchors and print a error instead of crashing
|
[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
|
== Client modules
|
||||||
[bart] make possible to reload modules
|
[bart] make possible to reload modules
|
||||||
|
@ -73,11 +74,12 @@ change win32 mouse cursor icon
|
||||||
[bart] clean sprites cache periodically
|
[bart] clean sprites cache periodically
|
||||||
[bart] create a shader manager
|
[bart] create a shader manager
|
||||||
[bart] find a way to load map rendering styles
|
[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] cache screen creatures in a list on map
|
||||||
[bart] handle corrupt errors in dat/spr
|
[bart] handle corrupt errors in dat/spr
|
||||||
[bart] remake spr/dat using OTML and image files
|
[bart] remake spr/dat using OTML and image files
|
||||||
[bart] rework map tile rendering (cache visible tiles, etc)
|
[bart] rework map tile rendering (cache visible tiles, etc)
|
||||||
[bart] minimap windows
|
[bart] minimap window
|
||||||
[bart] draw lights using shaders
|
[bart] draw lights using shaders
|
||||||
[bart] limit FPS in options
|
[bart] limit FPS in options
|
||||||
[bart] resize map, right panel
|
[bart] resize map, right panel
|
||||||
|
|
|
@ -8,7 +8,7 @@ function PingBar.init()
|
||||||
pingLabel:applyStyle({ ['anchors.left'] = 'prev.right',
|
pingLabel:applyStyle({ ['anchors.left'] = 'prev.right',
|
||||||
['anchors.top'] = 'parent.top',
|
['anchors.top'] = 'parent.top',
|
||||||
['margin-top'] = 12,
|
['margin-top'] = 12,
|
||||||
['margin-left'] = 10,
|
['margin-left'] = 20,
|
||||||
font = 'verdana-11px-rounded',
|
font = 'verdana-11px-rounded',
|
||||||
color = '#FE6500',
|
color = '#FE6500',
|
||||||
width = 120,
|
width = 120,
|
||||||
|
|
|
@ -4,7 +4,7 @@ Module
|
||||||
author: OTClient team
|
author: OTClient team
|
||||||
website: https://github.com/edubart/otclient
|
website: https://github.com/edubart/otclient
|
||||||
|
|
||||||
autoLoad: false
|
autoLoad: true
|
||||||
autoLoadAntecedence: 1000
|
autoLoadAntecedence: 1000
|
||||||
|
|
||||||
onLoad: |
|
onLoad: |
|
||||||
|
|
|
@ -108,16 +108,16 @@ function Terminal.init()
|
||||||
terminalWidget:setVisible(false)
|
terminalWidget:setVisible(false)
|
||||||
|
|
||||||
terminalButton = TopMenu.addButton('terminalButton', 'Terminal (Ctrl + T)', '/core_styles/icons/terminal.png', Terminal.toggle)
|
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')
|
commandHistory = Settings.getList('terminal-history')
|
||||||
|
|
||||||
commandLineEdit = terminalWidget:getChildById('commandLineEdit')
|
commandLineEdit = terminalWidget:getChildById('commandLineEdit')
|
||||||
Hotkeys.bind('Up', function() navigateCommand(1) end, commandLineEdit)
|
Hotkeys.bindKeyDown('Up', function() navigateCommand(1) end, commandLineEdit)
|
||||||
Hotkeys.bind('Down', function() navigateCommand(-1) end, commandLineEdit)
|
Hotkeys.bindKeyDown('Down', function() navigateCommand(-1) end, commandLineEdit)
|
||||||
Hotkeys.bind('Tab', completeCommand, commandLineEdit)
|
Hotkeys.bindKeyDown('Tab', completeCommand, commandLineEdit)
|
||||||
Hotkeys.bind('Enter', doCommand, commandLineEdit)
|
Hotkeys.bindKeyDown('Enter', doCommand, commandLineEdit)
|
||||||
Hotkeys.bind('Return', doCommand, commandLineEdit)
|
Hotkeys.bindKeyDown('Return', doCommand, commandLineEdit)
|
||||||
|
|
||||||
terminalBuffer = terminalWidget:getChildById('terminalBuffer')
|
terminalBuffer = terminalWidget:getChildById('terminalBuffer')
|
||||||
Logger.setOnLog(onLog)
|
Logger.setOnLog(onLog)
|
||||||
|
@ -126,7 +126,7 @@ end
|
||||||
|
|
||||||
function Terminal.terminate()
|
function Terminal.terminate()
|
||||||
Settings.setList('terminal-history', commandHistory)
|
Settings.setList('terminal-history', commandHistory)
|
||||||
Hotkeys.unbind('Ctrl+T')
|
Hotkeys.unbindKeyDown('Ctrl+T')
|
||||||
Logger.setOnLog(nil)
|
Logger.setOnLog(nil)
|
||||||
terminalButton:destroy()
|
terminalButton:destroy()
|
||||||
terminalButton = nil
|
terminalButton = nil
|
||||||
|
|
|
@ -6,7 +6,8 @@ local loadBox
|
||||||
local characterList
|
local characterList
|
||||||
|
|
||||||
-- private functions
|
-- 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 keyboardModifiers == KeyboardNoModifier then
|
||||||
if keyCode == KeyUp then
|
if keyCode == KeyUp then
|
||||||
characterList:focusPreviousChild(ActiveFocusReason)
|
characterList:focusPreviousChild(ActiveFocusReason)
|
||||||
|
|
|
@ -57,7 +57,7 @@ end
|
||||||
-- public functions
|
-- public functions
|
||||||
function EnterGame.init()
|
function EnterGame.init()
|
||||||
enterGameButton = TopMenu.addButton('enterGameButton', 'Login (Ctrl + G)', '/core_styles/icons/login.png', EnterGame.openWindow)
|
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 = TopMenu.addButton('motdButton', 'Message of the day', '/core_styles/icons/motd.png', EnterGame.displayMotd)
|
||||||
motdButton:hide()
|
motdButton:hide()
|
||||||
enterGame = displayUI('entergame.otui')
|
enterGame = displayUI('entergame.otui')
|
||||||
|
@ -82,7 +82,7 @@ function EnterGame.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function EnterGame.terminate()
|
function EnterGame.terminate()
|
||||||
Hotkeys.unbind('Ctrl+G')
|
Hotkeys.unbindKeyDown('Ctrl+G')
|
||||||
enterGame:destroy()
|
enterGame:destroy()
|
||||||
enterGame = nil
|
enterGame = nil
|
||||||
enterGameButton:destroy()
|
enterGameButton:destroy()
|
||||||
|
|
|
@ -25,11 +25,11 @@ function Options.init()
|
||||||
optionsWindow = displayUI('options.otui')
|
optionsWindow = displayUI('options.otui')
|
||||||
optionsWindow:setVisible(false)
|
optionsWindow:setVisible(false)
|
||||||
optionsButton = TopMenu.addButton('settingsButton', 'Options (Ctrl+O)', '/core_styles/icons/settings.png', Options.toggle)
|
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
|
end
|
||||||
|
|
||||||
function Options.terminate()
|
function Options.terminate()
|
||||||
Hotkeys.unbind('Ctrl+O')
|
Hotkeys.unbindKeyDown('Ctrl+O')
|
||||||
optionsWindow:destroy()
|
optionsWindow:destroy()
|
||||||
optionsWindow = nil
|
optionsWindow = nil
|
||||||
optionsButton:destroy()
|
optionsButton:destroy()
|
||||||
|
|
|
@ -23,11 +23,11 @@ function TopMenu.init()
|
||||||
gameButtonsPanel = topMenu:getChildById('gameButtonsPanel')
|
gameButtonsPanel = topMenu:getChildById('gameButtonsPanel')
|
||||||
|
|
||||||
TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout)
|
TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout)
|
||||||
Hotkeys.bind('Ctrl+Q', onLogout)
|
Hotkeys.bindKeyDown('Ctrl+Q', onLogout)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TopMenu.terminate()
|
function TopMenu.terminate()
|
||||||
Hotkeys.unbind('Ctrl+Q')
|
Hotkeys.unbindKeyDown('Ctrl+Q')
|
||||||
leftButtonsPanel = nil
|
leftButtonsPanel = nil
|
||||||
rightButtonsPanel = nil
|
rightButtonsPanel = nil
|
||||||
topMenu:destroy()
|
topMenu:destroy()
|
||||||
|
|
|
@ -45,6 +45,15 @@ AlignTopCenter = 20
|
||||||
AlignBottomCenter = 24
|
AlignBottomCenter = 24
|
||||||
AlignCenter = 48
|
AlignCenter = 48
|
||||||
|
|
||||||
|
North = 0
|
||||||
|
East = 1
|
||||||
|
South = 2
|
||||||
|
West = 3
|
||||||
|
NorthEast = 4
|
||||||
|
SouthEast = 5
|
||||||
|
SouthWest = 6
|
||||||
|
NorthWest = 7
|
||||||
|
|
||||||
|
|
||||||
KeyUnknown = 0
|
KeyUnknown = 0
|
||||||
KeyEscape = 1
|
KeyEscape = 1
|
||||||
|
|
|
@ -58,10 +58,10 @@ local function determineKeyComboDesc(keyCode, keyboardModifiers)
|
||||||
return translateKeyCombo(keyCombo)
|
return translateKeyCombo(keyCombo)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function onWidgetKeyPress(widget, keyCode, keyText, keyboardModifiers)
|
local function onWidgetKeyDown(widget, keyCode, keyboardModifiers)
|
||||||
if keyCode == KeyUnknown then return end
|
if keyCode == KeyUnknown then return end
|
||||||
local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
|
local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers)
|
||||||
local callback = widget.boundKeyCombos[keyComboDesc]
|
local callback = widget.boundKeyDownCombos[keyComboDesc]
|
||||||
if callback then
|
if callback then
|
||||||
callback()
|
callback()
|
||||||
return true
|
return true
|
||||||
|
@ -69,29 +69,57 @@ local function onWidgetKeyPress(widget, keyCode, keyText, keyboardModifiers)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function connectWidgetHotkeyEvent(widget)
|
local function onWidgetKeyPress(widget, keyCode, keyboardModifiers, wouldFilter)
|
||||||
if widget.boundKeyCombos then return end
|
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 })
|
connect(widget, { onKeyPress = onWidgetKeyPress })
|
||||||
widget.boundKeyCombos = {}
|
widget.boundKeyPressCombos = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- public functions
|
-- public functions
|
||||||
function Hotkeys.bind(keyComboDesc, callback, widget)
|
function Hotkeys.bindKeyDown(keyComboDesc, callback, widget)
|
||||||
widget = widget or rootWidget
|
widget = widget or rootWidget
|
||||||
connectWidgetHotkeyEvent(widget)
|
connectKeyDownEvent(widget)
|
||||||
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
||||||
if keyComboDesc then
|
if keyComboDesc then
|
||||||
widget.boundKeyCombos[keyComboDesc] = callback
|
widget.boundKeyDownCombos[keyComboDesc] = callback
|
||||||
else
|
else
|
||||||
error('key combo \'' .. keyComboDesc .. '\' is failed')
|
error('key combo \'' .. keyComboDesc .. '\' is failed')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Hotkeys.unbind(keyComboDesc, widget)
|
function Hotkeys.bindKeyPress(keyComboDesc, callback, widget)
|
||||||
widget = widget or rootWidget
|
widget = widget or rootWidget
|
||||||
if widget.boundKeyCombos == nil then return end
|
connectKeyPressEvent(widget)
|
||||||
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
||||||
if keyComboDesc then
|
if keyComboDesc then
|
||||||
widget.boundKeyCombos[keyComboDesc] = nil
|
widget.boundKeyPressCombos[keyComboDesc] = callback
|
||||||
|
else
|
||||||
|
error('key combo \'' .. keyComboDesc .. '\' is failed')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hotkeys.unbindKeyDown(keyComboDesc, widget)
|
||||||
|
widget = widget or rootWidget
|
||||||
|
if widget.boundKeyDownCombos == nil then return end
|
||||||
|
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
||||||
|
if keyComboDesc then
|
||||||
|
widget.boundKeyDownCombos[keyComboDesc] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ local displayedMenuList = {}
|
||||||
function UIPopupMenu.create()
|
function UIPopupMenu.create()
|
||||||
local menu = UIPopupMenu.internalCreate()
|
local menu = UIPopupMenu.internalCreate()
|
||||||
local layout = UIVerticalLayout.create(menu)
|
local layout = UIVerticalLayout.create(menu)
|
||||||
layout:setFitParent(true)
|
layout:setFitChildren(true)
|
||||||
menu:setLayout(layout)
|
menu:setLayout(layout)
|
||||||
return menu
|
return menu
|
||||||
end
|
end
|
||||||
|
@ -53,7 +53,8 @@ function UIPopupMenu:onMousePress(mousePos, mouseButton)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function UIPopupMenu:onKeyPress(keyCode, keyText, keyboardModifiers)
|
function UIPopupMenu:onKeyPress(keyCode, keyboardModifiers, wouldFilter)
|
||||||
|
if wouldFilter then return end
|
||||||
if keyCode == KeyEscape then
|
if keyCode == KeyEscape then
|
||||||
self:destroy()
|
self:destroy()
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -6,7 +6,8 @@ function UIWindow.create()
|
||||||
return window
|
return window
|
||||||
end
|
end
|
||||||
|
|
||||||
function UIWindow:onKeyPress(keyCode, keyText, keyboardModifiers)
|
function UIWindow:onKeyPress(keyCode, keyboardModifiers, wouldFilter)
|
||||||
|
if wouldFilter then return end
|
||||||
if keyboardModifiers == KeyboardNoModifier then
|
if keyboardModifiers == KeyboardNoModifier then
|
||||||
if keyCode == KeyReturn or keyCode == KeyEnter then
|
if keyCode == KeyReturn or keyCode == KeyEnter then
|
||||||
signalcall(self.onEnter, self)
|
signalcall(self.onEnter, self)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
-- private functions
|
-- 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 keyboardModifiers == KeyboardCtrlModifier then
|
||||||
if keyCode == KeyG then
|
if keyCode == KeyG then
|
||||||
CharacterList.show()
|
CharacterList.show()
|
||||||
|
@ -17,6 +18,17 @@ function Game.createInterface()
|
||||||
Background.hide()
|
Background.hide()
|
||||||
CharacterList.destroyLoadBox()
|
CharacterList.destroyLoadBox()
|
||||||
Game.gameUi = displayUI('game.otui')
|
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)
|
rootWidget:moveChildToIndex(Game.gameUi, 1)
|
||||||
Game.gameMapPanel = Game.gameUi:getChildById('gameMapPanel')
|
Game.gameMapPanel = Game.gameUi:getChildById('gameMapPanel')
|
||||||
Game.gameRightPanel = Game.gameUi:getChildById('gameRightPanel')
|
Game.gameRightPanel = Game.gameUi:getChildById('gameRightPanel')
|
||||||
|
|
|
@ -48,10 +48,10 @@ function Console.create()
|
||||||
Console.addChannel('Default', 0)
|
Console.addChannel('Default', 0)
|
||||||
Console.addTab('Server Log')
|
Console.addTab('Server Log')
|
||||||
|
|
||||||
Hotkeys.bind('Tab', function() consoleTabBar:selectNextTab() end, consolePanel)
|
Hotkeys.bindKeyDown('Tab', function() consoleTabBar:selectNextTab() end, consolePanel)
|
||||||
Hotkeys.bind('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel)
|
Hotkeys.bindKeyDown('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel)
|
||||||
Hotkeys.bind('Enter', Console.sendCurrentMessage, consolePanel)
|
Hotkeys.bindKeyDown('Enter', Console.sendCurrentMessage, consolePanel)
|
||||||
Hotkeys.bind('Return', Console.sendCurrentMessage, consolePanel)
|
Hotkeys.bindKeyDown('Return', Console.sendCurrentMessage, consolePanel)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Console.destroy()
|
function Console.destroy()
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
-- this file use loaded after everything is loaded and initialized
|
-- this file use loaded after everything is loaded and initialized
|
||||||
-- you can place any custom user code here
|
-- you can place any custom user code here
|
||||||
|
|
||||||
Hotkeys.bind('F1', function() Game.talk('exura gran') end)
|
Hotkeys.bindKeyDown('F1', function() Game.talk('exura gran') end)
|
||||||
Hotkeys.bind('F2', function() Game.talk('exori mort') end)
|
Hotkeys.bindKeyDown('F2', function() Game.talk('exori mort') end)
|
||||||
Hotkeys.bind('F3', function() Game.talk('exori frigo') end)
|
Hotkeys.bindKeyDown('F3', function() Game.talk('exori frigo') end)
|
||||||
Hotkeys.bind('F4', function() Game.talk('exevo vis hur') end)
|
Hotkeys.bindKeyDown('F4', function() Game.talk('exevo vis hur') end)
|
||||||
Hotkeys.bind('F5', function() Game.talk('utani gran hur') end)
|
Hotkeys.bindKeyDown('F5', function() Game.talk('utani gran hur') end)
|
||||||
Hotkeys.bind('F6', function() Game.talk('exani tera') end)
|
Hotkeys.bindKeyDown('F6', function() Game.talk('exani tera') end)
|
||||||
|
|
||||||
local function reload()
|
local function reload()
|
||||||
runscript('otclientrc.lua')
|
runscript('otclientrc.lua')
|
||||||
TextMessage.displayEventAdvance('Script otclientrc.lua reloaded.')
|
TextMessage.displayEventAdvance('Script otclientrc.lua reloaded.')
|
||||||
print('Script otclient.rc lua reloaded')
|
print('Script otclient.rc lua reloaded')
|
||||||
end
|
end
|
||||||
Hotkeys.bind('Ctrl+R', reload)
|
Hotkeys.bindKeyDown('Ctrl+R', reload)
|
||||||
|
|
||||||
rcloaded = true
|
rcloaded = true
|
||||||
|
|
|
@ -228,6 +228,8 @@ namespace Fw
|
||||||
|
|
||||||
enum InputEventType {
|
enum InputEventType {
|
||||||
NoInputEvent = 0,
|
NoInputEvent = 0,
|
||||||
|
KeyTextInputEvent,
|
||||||
|
KeyDownInputEvent,
|
||||||
KeyPressInputEvent,
|
KeyPressInputEvent,
|
||||||
KeyReleaseInputEvent,
|
KeyReleaseInputEvent,
|
||||||
MousePressInputEvent,
|
MousePressInputEvent,
|
||||||
|
|
|
@ -76,10 +76,8 @@ void ConfigManager::setList(const std::string& key, const std::vector<std::strin
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OTMLNodePtr child = OTMLNode::create(key, true);
|
OTMLNodePtr child = OTMLNode::create(key, true);
|
||||||
for(const std::string& value : list) {
|
for(const std::string& value : list)
|
||||||
child->writeIn(value);
|
child->writeIn(value);
|
||||||
dump << "insert" << value;
|
|
||||||
}
|
|
||||||
m_confsDoc->addChild(child);
|
m_confsDoc->addChild(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,30 @@
|
||||||
#include "declarations.h"
|
#include "declarations.h"
|
||||||
|
|
||||||
struct InputEvent {
|
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::InputEventType type;
|
||||||
Fw::MouseWheelDirection wheelDirection;
|
Fw::MouseWheelDirection wheelDirection;
|
||||||
Fw::MouseButton mouseButton;
|
Fw::MouseButton mouseButton;
|
||||||
int keyboardModifiers;
|
|
||||||
std::string keyText;
|
|
||||||
Fw::Key keyCode;
|
Fw::Key keyCode;
|
||||||
|
std::string keyText;
|
||||||
|
int keyboardModifiers;
|
||||||
Point mousePos;
|
Point mousePos;
|
||||||
Point mouseMoved;
|
Point mouseMoved;
|
||||||
|
bool wouldFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,7 +29,7 @@ Particle::Particle(const Point& pos, const Size& startSize, const Size& finalSiz
|
||||||
m_colors = colors;
|
m_colors = colors;
|
||||||
m_colorsStops = colorsStops;
|
m_colorsStops = colorsStops;
|
||||||
|
|
||||||
m_position = PointF(pos.x, pos.y);
|
m_pos = PointF(pos.x, pos.y);
|
||||||
m_startSize = startSize;
|
m_startSize = startSize;
|
||||||
m_finalSize = finalSize;
|
m_finalSize = finalSize;
|
||||||
m_velocity = velocity;
|
m_velocity = velocity;
|
||||||
|
@ -80,18 +80,18 @@ void Particle::updatePosition(double elapsedTime)
|
||||||
PointF delta = m_velocity * elapsedTime;
|
PointF delta = m_velocity * elapsedTime;
|
||||||
delta.y *= -1; // painter orientate Y axis in the inverse direction
|
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;
|
mustRedraw = true;
|
||||||
m_position += delta;
|
m_pos += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update acceleration
|
// update acceleration
|
||||||
m_velocity += m_acceleration * elapsedTime;
|
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()
|
void Particle::updateSize()
|
||||||
|
|
|
@ -36,10 +36,10 @@ public:
|
||||||
|
|
||||||
bool hasFinished() { return m_finished; }
|
bool hasFinished() { return m_finished; }
|
||||||
|
|
||||||
PointF getPos() { return m_position; }
|
PointF getPos() { return m_pos; }
|
||||||
PointF getVelocity() { return m_velocity; }
|
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; }
|
void setVelocity(const PointF& velocity) { m_velocity = velocity; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -51,7 +51,7 @@ private:
|
||||||
std::vector<Color> m_colors;
|
std::vector<Color> m_colors;
|
||||||
std::vector<float> m_colorsStops;
|
std::vector<float> m_colorsStops;
|
||||||
TexturePtr m_texture;
|
TexturePtr m_texture;
|
||||||
PointF m_position;
|
PointF m_pos;
|
||||||
PointF m_velocity;
|
PointF m_velocity;
|
||||||
PointF m_acceleration;
|
PointF m_acceleration;
|
||||||
Size m_size, m_startSize, m_finalSize;
|
Size m_size, m_startSize, m_finalSize;
|
||||||
|
|
|
@ -115,7 +115,7 @@ bool AttractionAffector::load(const OTMLNodePtr& node)
|
||||||
|
|
||||||
for(const OTMLNodePtr& childNode : node->children()) {
|
for(const OTMLNodePtr& childNode : node->children()) {
|
||||||
if(childNode->tag() == "position")
|
if(childNode->tag() == "position")
|
||||||
m_position = childNode->value<Point>();
|
m_pos = childNode->value<Point>();
|
||||||
else if(childNode->tag() == "acceleration")
|
else if(childNode->tag() == "acceleration")
|
||||||
m_acceleration = childNode->value<float>();
|
m_acceleration = childNode->value<float>();
|
||||||
else if(childNode->tag() == "velocity-reduction-percent")
|
else if(childNode->tag() == "velocity-reduction-percent")
|
||||||
|
@ -132,7 +132,7 @@ void AttractionAffector::updateParticle(const ParticlePtr& particle, double elap
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PointF pPosition = particle->getPos();
|
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)
|
if(d.length() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
void updateParticle(const ParticlePtr& particle, double elapsedTime);
|
void updateParticle(const ParticlePtr& particle, double elapsedTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point m_position;
|
Point m_pos;
|
||||||
float m_acceleration, m_reduction;
|
float m_acceleration, m_reduction;
|
||||||
bool m_repelish;
|
bool m_repelish;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@ ParticleEmitter::ParticleEmitter(const ParticleSystemPtr& parent)
|
||||||
{
|
{
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
|
|
||||||
m_position = Point(0, 0);
|
m_pos = Point(0, 0);
|
||||||
m_duration = -1;
|
m_duration = -1;
|
||||||
m_delay = 0;
|
m_delay = 0;
|
||||||
m_burstRate = 1; m_burstCount = 32;
|
m_burstRate = 1; m_burstCount = 32;
|
||||||
|
@ -65,7 +65,7 @@ bool ParticleEmitter::load(const OTMLNodePtr& node)
|
||||||
for(const OTMLNodePtr& childNode : node->children()) {
|
for(const OTMLNodePtr& childNode : node->children()) {
|
||||||
// self related
|
// self related
|
||||||
if(childNode->tag() == "position")
|
if(childNode->tag() == "position")
|
||||||
m_position = childNode->value<Point>();
|
m_pos = childNode->value<Point>();
|
||||||
else if(childNode->tag() == "duration")
|
else if(childNode->tag() == "duration")
|
||||||
m_duration = childNode->value<float>();
|
m_duration = childNode->value<float>();
|
||||||
else if(childNode->tag() == "delay")
|
else if(childNode->tag() == "delay")
|
||||||
|
@ -199,7 +199,7 @@ void ParticleEmitter::update(double elapsedTime)
|
||||||
float pRadius = Fw::randomRange(m_pMinPositionRadius, m_pMaxPositionRadius);
|
float pRadius = Fw::randomRange(m_pMinPositionRadius, m_pMaxPositionRadius);
|
||||||
float pAngle = Fw::randomRange(m_pMinPositionAngle, m_pMaxPositionAngle);
|
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) {
|
for(int p = 0; p < m_burstCount; ++p) {
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ private:
|
||||||
ParticleSystemWeakPtr m_parent;
|
ParticleSystemWeakPtr m_parent;
|
||||||
|
|
||||||
// self related
|
// self related
|
||||||
Point m_position;
|
Point m_pos;
|
||||||
float m_duration, m_delay;
|
float m_duration, m_delay;
|
||||||
double m_elapsedTime;
|
double m_elapsedTime;
|
||||||
bool m_finished, m_active;
|
bool m_finished, m_active;
|
||||||
|
|
|
@ -294,12 +294,12 @@ void Application::registerLuaFunctions()
|
||||||
g_lua.bindClassMemberFunction<UIBoxLayout>("setFitChildren", &UIBoxLayout::setFitChildren);
|
g_lua.bindClassMemberFunction<UIBoxLayout>("setFitChildren", &UIBoxLayout::setFitChildren);
|
||||||
|
|
||||||
// UIVerticalLayout
|
// UIVerticalLayout
|
||||||
g_lua.registerClass<UIVerticalLayout, UILayout>();
|
g_lua.registerClass<UIVerticalLayout, UIBoxLayout>();
|
||||||
g_lua.bindClassStaticFunction<UIVerticalLayout>("create", [](UIWidgetPtr parent){ return UIVerticalLayoutPtr(new UIVerticalLayout(parent)); } );
|
g_lua.bindClassStaticFunction<UIVerticalLayout>("create", [](UIWidgetPtr parent){ return UIVerticalLayoutPtr(new UIVerticalLayout(parent)); } );
|
||||||
g_lua.bindClassMemberFunction<UIVerticalLayout>("setAlignBottom", &UIVerticalLayout::setAlignBottom);
|
g_lua.bindClassMemberFunction<UIVerticalLayout>("setAlignBottom", &UIVerticalLayout::setAlignBottom);
|
||||||
|
|
||||||
// UIHorizontalLayout
|
// UIHorizontalLayout
|
||||||
g_lua.registerClass<UIHorizontalLayout, UILayout>();
|
g_lua.registerClass<UIHorizontalLayout, UIBoxLayout>();
|
||||||
g_lua.bindClassStaticFunction<UIHorizontalLayout>("create", [](UIWidgetPtr parent){ return UIHorizontalLayoutPtr(new UIHorizontalLayout(parent)); } );
|
g_lua.bindClassStaticFunction<UIHorizontalLayout>("create", [](UIWidgetPtr parent){ return UIHorizontalLayoutPtr(new UIHorizontalLayout(parent)); } );
|
||||||
g_lua.bindClassMemberFunction<UIHorizontalLayout>("setAlignRight", &UIHorizontalLayout::setAlignRight);
|
g_lua.bindClassMemberFunction<UIHorizontalLayout>("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", "getY", std::bind(&PlatformWindow::getY, &g_window));
|
||||||
g_lua.bindClassStaticFunction("g_window", "getMousePos", std::bind(&PlatformWindow::getMousePos, &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", "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", "isVisible", std::bind(&PlatformWindow::isVisible, &g_window));
|
||||||
g_lua.bindClassStaticFunction("g_window", "isFullscreen", std::bind(&PlatformWindow::isFullscreen, &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));
|
g_lua.bindClassStaticFunction("g_window", "isMaximized", std::bind(&PlatformWindow::isMaximized, &g_window));
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
WIN32Window window;
|
WIN32Window window;
|
||||||
#else
|
#else
|
||||||
#include "x11window.h"
|
#include "x11window.h"
|
||||||
|
#include <framework/core/clock.h>
|
||||||
X11Window window;
|
X11Window window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -39,3 +40,83 @@ void PlatformWindow::updateUnmaximizedCoords()
|
||||||
m_unmaximizedSize = m_size;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,15 @@
|
||||||
|
|
||||||
#include <framework/global.h>
|
#include <framework/global.h>
|
||||||
#include <framework/core/inputevent.h>
|
#include <framework/core/inputevent.h>
|
||||||
|
#include <framework/core/timer.h>
|
||||||
|
|
||||||
class PlatformWindow
|
class PlatformWindow
|
||||||
{
|
{
|
||||||
|
enum {
|
||||||
|
KEY_PRESS_REPEAT_INTERVAL = 30,
|
||||||
|
KEY_PRESS_REPEAT_DELAY = 500
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::function<void(const Size&)> OnResizeCallback;
|
typedef std::function<void(const Size&)> OnResizeCallback;
|
||||||
typedef std::function<void(const InputEvent&)> OnInputEventCallback;
|
typedef std::function<void(const InputEvent&)> OnInputEventCallback;
|
||||||
|
|
||||||
|
@ -72,6 +78,7 @@ public:
|
||||||
int getY() { return m_pos.y; }
|
int getY() { return m_pos.y; }
|
||||||
Point getMousePos() { return m_inputEvent.mousePos; }
|
Point getMousePos() { return m_inputEvent.mousePos; }
|
||||||
int getKeyboardModifiers() { return m_inputEvent.keyboardModifiers; }
|
int getKeyboardModifiers() { return m_inputEvent.keyboardModifiers; }
|
||||||
|
bool isKeyPressed(Fw::Key keyCode) { return m_keysState[keyCode]; }
|
||||||
|
|
||||||
bool isVisible() { return m_visible; }
|
bool isVisible() { return m_visible; }
|
||||||
bool isFullscreen() { return m_fullscreen; }
|
bool isFullscreen() { return m_fullscreen; }
|
||||||
|
@ -85,6 +92,16 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void updateUnmaximizedCoords();
|
void updateUnmaximizedCoords();
|
||||||
|
|
||||||
|
void processKeyDown(Fw::Key keyCode);
|
||||||
|
void processKeyRelease(Fw::Key keyCode);
|
||||||
|
void fireKeysPress();
|
||||||
|
|
||||||
|
std::map<int, Fw::Key> m_keyMap;
|
||||||
|
std::map<Fw::Key, Boolean<false>> m_keysState;
|
||||||
|
std::map<Fw::Key, ticks_t> m_firstKeysPress;
|
||||||
|
std::map<Fw::Key, ticks_t> m_lastKeysPress;
|
||||||
|
Timer m_keyPressTimer;
|
||||||
|
|
||||||
Size m_size;
|
Size m_size;
|
||||||
Point m_pos;
|
Point m_pos;
|
||||||
Size m_unmaximizedSize;
|
Size m_unmaximizedSize;
|
||||||
|
|
|
@ -35,7 +35,6 @@ WIN32Window::WIN32Window()
|
||||||
m_maximized = false;
|
m_maximized = false;
|
||||||
m_minimumSize = Size(16,16);
|
m_minimumSize = Size(16,16);
|
||||||
m_size = m_minimumSize;
|
m_size = m_minimumSize;
|
||||||
m_inputEvent.keyboardModifiers = 0;
|
|
||||||
|
|
||||||
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
||||||
m_keyMap[VK_TAB] = Fw::KeyTab;
|
m_keyMap[VK_TAB] = Fw::KeyTab;
|
||||||
|
|
|
@ -82,7 +82,6 @@ private:
|
||||||
HGLRC m_glContext;
|
HGLRC m_glContext;
|
||||||
bool m_maximized;
|
bool m_maximized;
|
||||||
Size m_minimumSize;
|
Size m_minimumSize;
|
||||||
std::map<int, Fw::Key> m_keyMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,7 +39,6 @@ X11Window::X11Window()
|
||||||
m_screen = 0;
|
m_screen = 0;
|
||||||
m_wmDelete = 0;
|
m_wmDelete = 0;
|
||||||
m_size = Size(16,16);
|
m_size = Size(16,16);
|
||||||
m_inputEvent.keyboardModifiers = 0;
|
|
||||||
|
|
||||||
#ifndef OPENGL_ES2
|
#ifndef OPENGL_ES2
|
||||||
m_glxContext = 0;
|
m_glxContext = 0;
|
||||||
|
@ -526,33 +525,41 @@ void X11Window::poll()
|
||||||
while(XPending(m_display) > 0) {
|
while(XPending(m_display) > 0) {
|
||||||
XNextEvent(m_display, &event);
|
XNextEvent(m_display, &event);
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
repatedKeyRelease = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// call filter because xim will discard KeyPress events when keys still composing
|
||||||
if(XFilterEvent(&event, m_window))
|
if(XFilterEvent(&event, m_window))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// discard events of repeated key releases
|
// discard repated key releases
|
||||||
if(event.type == KeyRelease && XPending(m_display)) {
|
if(repatedKeyRelease)
|
||||||
XPeekEvent(m_display, &peekEvent);
|
continue;
|
||||||
if((peekEvent.type == KeyPress) &&
|
|
||||||
(peekEvent.xkey.keycode == event.xkey.keycode) &&
|
|
||||||
((peekEvent.xkey.time-event.xkey.time) < 2))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case ClientMessage: {
|
case ClientMessage: {
|
||||||
|
@ -614,55 +621,44 @@ void X11Window::poll()
|
||||||
XFlush(m_display);
|
XFlush(m_display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KeyPress:
|
// process text events
|
||||||
case KeyRelease: {
|
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;
|
KeySym keysym;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
memset(buf, 0, 32);
|
memset(buf, 0, 32);
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
// lookup for keyText
|
// 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
|
||||||
if(m_xic) { // with xim we can get latin1 input correctly
|
Status status;
|
||||||
Status status;
|
len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &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
|
||||||
} else { // otherwise use XLookupString, but often it doesn't work right with dead keys
|
static XComposeStatus compose = {NULL, 0};
|
||||||
static XComposeStatus compose = {NULL, 0};
|
len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XKeyEvent xkey = event.xkey;
|
// filter unwanted characters
|
||||||
xkey.state = xkey.state & ~(ShiftMask);
|
if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape)
|
||||||
len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0);
|
break;
|
||||||
if(len > 0 && m_inputEvent.keyText.length() == 0 && keysym != XK_BackSpace &&
|
std::string text = buf;
|
||||||
keysym != XK_Return &&
|
|
||||||
keysym != XK_Delete &&
|
|
||||||
keysym != XK_Escape)
|
|
||||||
m_inputEvent.keyText = buf;
|
|
||||||
|
|
||||||
if(m_keyMap.find(keysym) != m_keyMap.end())
|
//logDebug("char: ", buf[0], " code: ", (int)((uchar)buf[0]));
|
||||||
m_inputEvent.keyCode = m_keyMap[keysym];
|
|
||||||
|
|
||||||
m_inputEvent.type = (event.type == KeyPress) ? Fw::KeyPressInputEvent : Fw::KeyReleaseInputEvent;
|
if(m_onInputEvent && text.length() > 0) {
|
||||||
if(m_inputEvent.keyCode != Fw::KeyUnknown || !m_inputEvent.keyText.empty())
|
m_inputEvent.reset(Fw::KeyTextInputEvent);
|
||||||
|
m_inputEvent.keyText = text;
|
||||||
m_onInputEvent(m_inputEvent);
|
m_onInputEvent(m_inputEvent);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
case ButtonRelease: {
|
case ButtonRelease: {
|
||||||
|
m_inputEvent.reset();
|
||||||
m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
|
m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
|
||||||
switch(event.xbutton.button) {
|
switch(event.xbutton.button) {
|
||||||
case Button1:
|
case Button1:
|
||||||
|
@ -694,6 +690,7 @@ void X11Window::poll()
|
||||||
}
|
}
|
||||||
|
|
||||||
case MotionNotify: {
|
case MotionNotify: {
|
||||||
|
m_inputEvent.reset();
|
||||||
m_inputEvent.type = Fw::MouseMoveInputEvent;
|
m_inputEvent.type = Fw::MouseMoveInputEvent;
|
||||||
Point newMousePos(event.xbutton.x, event.xbutton.y);
|
Point newMousePos(event.xbutton.x, event.xbutton.y);
|
||||||
m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
|
m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
|
||||||
|
@ -722,6 +719,8 @@ void X11Window::poll()
|
||||||
|
|
||||||
if(needsResizeUpdate && m_onResize)
|
if(needsResizeUpdate && m_onResize)
|
||||||
m_onResize(m_size);
|
m_onResize(m_size);
|
||||||
|
|
||||||
|
fireKeysPress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Window::swapBuffers()
|
void X11Window::swapBuffers()
|
||||||
|
|
|
@ -93,7 +93,6 @@ private:
|
||||||
int m_screen;
|
int m_screen;
|
||||||
Atom m_wmDelete;
|
Atom m_wmDelete;
|
||||||
std::string m_clipboardText;
|
std::string m_clipboardText;
|
||||||
std::map<int, Fw::Key> m_keyMap;
|
|
||||||
|
|
||||||
#ifndef OPENGL_ES2
|
#ifndef OPENGL_ES2
|
||||||
GLXContext m_glxContext;
|
GLXContext m_glxContext;
|
||||||
|
|
|
@ -389,6 +389,8 @@ void UILineEdit::onStyleApply(const std::string& styleName, const OTMLNodePtr& s
|
||||||
setTextHorizontalMargin(node->value<int>());
|
setTextHorizontalMargin(node->value<int>());
|
||||||
else if(node->tag() == "always-active")
|
else if(node->tag() == "always-active")
|
||||||
setAlwaysActive(node->value<bool>());
|
setAlwaysActive(node->value<bool>());
|
||||||
|
//else if(node->tag() == "disable-arrow-navitation")
|
||||||
|
// setArrowNavigation(node->value<bool>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,34 +411,41 @@ void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason)
|
||||||
UIWidget::onFocusChange(focused, 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;
|
return true;
|
||||||
|
|
||||||
if(keyCode == Fw::KeyDelete) // erase right character
|
if(!wouldFilter) {
|
||||||
removeCharacter(true);
|
if(keyCode == Fw::KeyDelete) // erase right character
|
||||||
else if(keyCode == Fw::KeyBackspace) // erase left character {
|
removeCharacter(true);
|
||||||
removeCharacter(false);
|
else if(keyCode == Fw::KeyBackspace) // erase left character {
|
||||||
else if(keyCode == Fw::KeyRight) // move cursor right
|
removeCharacter(false);
|
||||||
moveCursor(true);
|
else if(keyCode == Fw::KeyRight) // move cursor right
|
||||||
else if(keyCode == Fw::KeyLeft) // move cursor left
|
moveCursor(true);
|
||||||
moveCursor(false);
|
else if(keyCode == Fw::KeyLeft) // move cursor left
|
||||||
else if(keyCode == Fw::KeyHome) // move cursor to first character
|
moveCursor(false);
|
||||||
setCursorPos(0);
|
else if(keyCode == Fw::KeyHome) // move cursor to first character
|
||||||
else if(keyCode == Fw::KeyEnd) // move cursor to last character
|
setCursorPos(0);
|
||||||
setCursorPos(m_text.length());
|
else if(keyCode == Fw::KeyEnd) // move cursor to last character
|
||||||
else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
|
setCursorPos(m_text.length());
|
||||||
appendText(g_window.getClipboardText());
|
else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
|
||||||
else if(keyCode == Fw::KeyTab) {
|
appendText(g_window.getClipboardText());
|
||||||
if(!m_alwaysActive) {
|
else if(keyCode == Fw::KeyTab) {
|
||||||
if(UIWidgetPtr parent = getParent())
|
if(!m_alwaysActive) {
|
||||||
parent->focusNextChild(Fw::TabFocusReason);
|
if(UIWidgetPtr parent = getParent())
|
||||||
}
|
parent->focusNextChild(Fw::TabFocusReason);
|
||||||
} else if(!keyText.empty() && (keyboardModifiers == Fw::KeyboardNoModifier || keyboardModifiers == Fw::KeyboardShiftModifier))
|
}
|
||||||
appendText(keyText);
|
} else
|
||||||
else
|
return false;
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UILineEdit::onKeyText(const std::string& keyText)
|
||||||
|
{
|
||||||
|
appendText(keyText);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ protected:
|
||||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||||
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
|
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);
|
virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -59,11 +59,17 @@ void UIManager::inputEvent(const InputEvent& event)
|
||||||
{
|
{
|
||||||
m_isOnInputEvent = true;
|
m_isOnInputEvent = true;
|
||||||
switch(event.type) {
|
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:
|
case Fw::KeyPressInputEvent:
|
||||||
m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyText, event.keyboardModifiers);
|
m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyboardModifiers, event.wouldFilter);
|
||||||
break;
|
break;
|
||||||
case Fw::KeyReleaseInputEvent:
|
case Fw::KeyReleaseInputEvent:
|
||||||
m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers);
|
m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyboardModifiers);
|
||||||
break;
|
break;
|
||||||
case Fw::MousePressInputEvent:
|
case Fw::MousePressInputEvent:
|
||||||
m_keyboardReceiver->propagateOnMousePress(event.mousePos, event.mouseButton);
|
m_keyboardReceiver->propagateOnMousePress(event.mousePos, event.mouseButton);
|
||||||
|
|
|
@ -1053,14 +1053,24 @@ void UIWidget::onHoverChange(bool hovered)
|
||||||
g_ui.getRootWidget()->updateState(Fw::HoverState);
|
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<bool>("onKeyPress", keyCode, keyText, keyboardModifiers);
|
return callLuaField<bool>("onKeyText", keyText);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIWidget::onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers)
|
bool UIWidget::onKeyDown(uchar keyCode, int keyboardModifiers)
|
||||||
{
|
{
|
||||||
return callLuaField<bool>("onKeyRelease", keyCode, keyText, keyboardModifiers);
|
return callLuaField<bool>("onKeyDown", keyCode, keyboardModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UIWidget::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter)
|
||||||
|
{
|
||||||
|
return callLuaField<bool>("onKeyPress", keyCode, keyboardModifiers, wouldFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UIWidget::onKeyRelease(uchar keyCode, int keyboardModifiers)
|
||||||
|
{
|
||||||
|
return callLuaField<bool>("onKeyRelease", keyCode, keyboardModifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
|
bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
|
||||||
|
@ -1086,7 +1096,7 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc
|
||||||
return callLuaField<bool>("onMouseWheel", mousePos, direction);
|
return callLuaField<bool>("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
|
// do a backup of children list, because it may change while looping it
|
||||||
UIWidgetList children;
|
UIWidgetList children;
|
||||||
|
@ -1101,14 +1111,58 @@ bool UIWidget::propagateOnKeyPress(uchar keyCode, std::string keyText, int keybo
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const UIWidgetPtr& child : children) {
|
for(const UIWidgetPtr& child : children) {
|
||||||
if(child->propagateOnKeyPress(keyCode, keyText, keyboardModifiers))
|
if(child->propagateOnKeyText(keyText))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return onKeyPress(keyCode, keyText, keyboardModifiers);
|
return onKeyText(keyText);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers)
|
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;
|
||||||
|
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->propagateOnKeyPress(keyCode, keyboardModifiers, wouldFilter))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return onKeyPress(keyCode, keyboardModifiers, wouldFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UIWidget::propagateOnKeyRelease(uchar keyCode, int keyboardModifiers)
|
||||||
{
|
{
|
||||||
// do a backup of children list, because it may change while looping it
|
// do a backup of children list, because it may change while looping it
|
||||||
UIWidgetList children;
|
UIWidgetList children;
|
||||||
|
@ -1123,11 +1177,11 @@ bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int key
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const UIWidgetPtr& child : children) {
|
for(const UIWidgetPtr& child : children) {
|
||||||
if(child->propagateOnKeyRelease(keyCode, keyText, keyboardModifiers))
|
if(child->propagateOnKeyRelease(keyCode, keyboardModifiers))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return onKeyRelease(keyCode, keyText, keyboardModifiers);
|
return onKeyRelease(keyCode, keyboardModifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIWidget::propagateOnMousePress(const Point& mousePos, Fw::MouseButton button)
|
bool UIWidget::propagateOnMousePress(const Point& mousePos, Fw::MouseButton button)
|
||||||
|
|
|
@ -161,15 +161,19 @@ protected:
|
||||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||||
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
|
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
|
||||||
virtual void onHoverChange(bool hovered);
|
virtual void onHoverChange(bool hovered);
|
||||||
virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
|
virtual bool onKeyText(const std::string& keyText);
|
||||||
virtual bool onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
|
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 bool onMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||||
virtual void onMouseRelease(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 onMouseMove(const Point& mousePos, const Point& mouseMoved);
|
||||||
virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction);
|
virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction);
|
||||||
|
|
||||||
bool propagateOnKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
|
bool propagateOnKeyText(const std::string& keyText);
|
||||||
bool propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
|
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);
|
bool propagateOnMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||||
void propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton button);
|
void propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton button);
|
||||||
bool propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved);
|
bool propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved);
|
||||||
|
|
|
@ -47,7 +47,7 @@ Creature::Creature() : Thing()
|
||||||
m_walkTimePerPixel = 1000.0/32.0;
|
m_walkTimePerPixel = 1000.0/32.0;
|
||||||
|
|
||||||
m_walking = false;
|
m_walking = false;
|
||||||
m_inverseWalking = true;
|
m_preWalking = false;
|
||||||
|
|
||||||
m_skull = Otc::SkullNone;
|
m_skull = Otc::SkullNone;
|
||||||
m_shield = Otc::ShieldNone;
|
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
|
// get walk direction
|
||||||
if(m_position.isInRange(position, 1, 1, 0)) {
|
Otc::Direction direction = oldPos.getDirectionFromPosition(newPos);
|
||||||
Otc::Direction direction = m_position.getDirectionFromPosition(position);
|
|
||||||
setDirection(direction);
|
|
||||||
|
|
||||||
if(inverse) {
|
// already pre walking to the same direction
|
||||||
Position positionDelta = m_position - position;
|
if(m_preWalking && preWalk && direction == m_direction)
|
||||||
m_walkOffset = Point(positionDelta.x * Map::NUM_TILE_PIXELS, positionDelta.y * Map::NUM_TILE_PIXELS);
|
return;
|
||||||
}
|
|
||||||
else
|
|
||||||
m_walkOffset = Point(0, 0);
|
|
||||||
|
|
||||||
// Diagonal walking lasts 3 times more.
|
// pre walking was already going on, just change to normal waking
|
||||||
int walkTimeFactor = 1;
|
if(m_preWalking && !preWalk && direction == m_direction) {
|
||||||
if(direction == Otc::NorthWest || direction == Otc::NorthEast || direction == Otc::SouthWest || direction == Otc::SouthEast)
|
m_preWalking = false;
|
||||||
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();
|
|
||||||
|
|
||||||
bool sameWalk = m_walking && !m_inverseWalking && inverse;
|
|
||||||
m_inverseWalking = inverse;
|
|
||||||
m_walking = true;
|
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();
|
updateWalk();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Teleport
|
|
||||||
else {
|
setDirection(direction);
|
||||||
m_walking = false;
|
|
||||||
m_walkOffset = Point(0, 0);
|
// diagonal walking lasts 3 times more.
|
||||||
m_animation = 0;
|
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)
|
void Creature::turn(Otc::Direction direction)
|
||||||
|
@ -252,7 +245,7 @@ void Creature::updateWalk()
|
||||||
int elapsedTicks = g_clock.ticksElapsed(m_walkStart);
|
int elapsedTicks = g_clock.ticksElapsed(m_walkStart);
|
||||||
int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
|
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)
|
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
|
||||||
m_walkOffset.y = 32 - totalPixelsWalked;
|
m_walkOffset.y = 32 - totalPixelsWalked;
|
||||||
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
|
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;
|
m_walkOffset.x = totalPixelsWalked - 32;
|
||||||
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
|
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
|
||||||
m_walkOffset.x = 32 - totalPixelsWalked;
|
m_walkOffset.x = 32 - totalPixelsWalked;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
|
if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest)
|
||||||
m_walkOffset.y = -totalPixelsWalked;
|
m_walkOffset.y = -totalPixelsWalked;
|
||||||
else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest)
|
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);
|
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);
|
cancelWalk(m_turnDirection);
|
||||||
else
|
} else
|
||||||
g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel);
|
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_walking = false;
|
||||||
m_walkStart = 0;
|
|
||||||
|
if(direction != Otc::InvalidDirection)
|
||||||
|
setDirection(direction);
|
||||||
|
|
||||||
if(m_outfit.getCategory() == ThingsType::Creature)
|
if(m_outfit.getCategory() == ThingsType::Creature)
|
||||||
m_animation = 0;
|
m_animation = 0;
|
||||||
m_walkOffset = Point(0, 0);
|
|
||||||
setDirection(direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::setName(const std::string& name)
|
void Creature::setName(const std::string& name)
|
||||||
|
@ -345,8 +343,7 @@ void Creature::setDirection(Otc::Direction direction)
|
||||||
m_xPattern = Otc::West;
|
m_xPattern = Otc::West;
|
||||||
else
|
else
|
||||||
m_xPattern = direction;
|
m_xPattern = direction;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_xPattern = 0;
|
m_xPattern = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +355,7 @@ void Creature::setOutfit(const Outfit& outfit)
|
||||||
if(m_outfit.getCategory() != ThingsType::Effect && outfit.getCategory() == ThingsType::Effect) {
|
if(m_outfit.getCategory() != ThingsType::Effect && outfit.getCategory() == ThingsType::Effect) {
|
||||||
auto self = asCreature();
|
auto self = asCreature();
|
||||||
g_dispatcher.scheduleEvent([self]() {
|
g_dispatcher.scheduleEvent([self]() {
|
||||||
self->updateAnimation();
|
self->updateInvisibleAnimation();
|
||||||
}, INVISIBLE_TICKS);
|
}, INVISIBLE_TICKS);
|
||||||
|
|
||||||
m_xPattern = 0;
|
m_xPattern = 0;
|
||||||
|
@ -433,7 +430,7 @@ void Creature::addVolatileSquare(uint8 color)
|
||||||
}, VOLATILE_SQUARE_DURATION);
|
}, VOLATILE_SQUARE_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::updateAnimation()
|
void Creature::updateInvisibleAnimation()
|
||||||
{
|
{
|
||||||
if(m_animation == 1)
|
if(m_animation == 1)
|
||||||
m_animation = 2;
|
m_animation = 2;
|
||||||
|
@ -447,7 +444,7 @@ void Creature::updateAnimation()
|
||||||
if(g_game.isOnline() && m_outfit.getCategory() == ThingsType::Effect) {
|
if(g_game.isOnline() && m_outfit.getCategory() == ThingsType::Effect) {
|
||||||
auto self = asCreature();
|
auto self = asCreature();
|
||||||
g_dispatcher.scheduleEvent([self]() {
|
g_dispatcher.scheduleEvent([self]() {
|
||||||
self->updateAnimation();
|
self->updateInvisibleAnimation();
|
||||||
}, INVISIBLE_TICKS);
|
}, INVISIBLE_TICKS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,3 +467,4 @@ ThingType *Creature::getType()
|
||||||
{
|
{
|
||||||
return g_thingsType.getThingType(m_outfit.getId(), m_outfit.getCategory());
|
return g_thingsType.getThingType(m_outfit.getId(), m_outfit.getCategory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,18 +73,19 @@ public:
|
||||||
uint8 getEmblem() { return m_emblem; }
|
uint8 getEmblem() { return m_emblem; }
|
||||||
bool getPassable() { return m_passable; }
|
bool getPassable() { return m_passable; }
|
||||||
|
|
||||||
void updateAnimation();
|
void updateInvisibleAnimation();
|
||||||
void updateShield();
|
void updateShield();
|
||||||
|
|
||||||
ThingType *getType();
|
ThingType *getType();
|
||||||
|
|
||||||
//virtual void walk(const Position& oldPos, const Position& newPos, bool inverse = true);
|
// walk related
|
||||||
virtual void walk(const Position& position, bool inverse = true);
|
void walk(const Position& oldPos, const Position& newPos, bool preWalk = false);
|
||||||
void turn(Otc::Direction direction);
|
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; }
|
Point getWalkOffset() { return m_walkOffset; }
|
||||||
|
|
||||||
bool isWalking() { return m_walking; }
|
bool isWalking() { return m_walking; }
|
||||||
|
bool isPreWalking() { return m_preWalking; }
|
||||||
|
|
||||||
CreaturePtr asCreature() { return std::static_pointer_cast<Creature>(shared_from_this()); }
|
CreaturePtr asCreature() { return std::static_pointer_cast<Creature>(shared_from_this()); }
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ protected:
|
||||||
Color m_informationColor;
|
Color m_informationColor;
|
||||||
|
|
||||||
ticks_t m_walkStart, m_walkEnd;
|
ticks_t m_walkStart, m_walkEnd;
|
||||||
bool m_walking, m_inverseWalking;
|
bool m_walking, m_preWalking;
|
||||||
float m_walkTimePerPixel;
|
float m_walkTimePerPixel;
|
||||||
Point m_walkOffset;
|
Point m_walkOffset;
|
||||||
Otc::Direction m_turnDirection;
|
Otc::Direction m_turnDirection;
|
||||||
|
|
|
@ -140,23 +140,22 @@ void Game::processInventoryChange(int slot, const ItemPtr& item)
|
||||||
|
|
||||||
void Game::processCreatureMove(const CreaturePtr& creature, const Position& oldPos, const Position& newPos)
|
void Game::processCreatureMove(const CreaturePtr& creature, const Position& oldPos, const Position& newPos)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// walk
|
// walk
|
||||||
if(oldPos.isInRange(newPos, 1, 1, 0)) {
|
if(oldPos.isInRange(newPos, 1, 1, 0)) {
|
||||||
Otc::Direction direction = oldPos.getDirectionFromPosition(newPos);
|
creature->walk(oldPos, newPos);
|
||||||
creature->setDirection(direction);
|
|
||||||
// teleport
|
// teleport
|
||||||
} else {
|
} else {
|
||||||
// stop animation on teleport
|
// stop walking on teleport
|
||||||
if(creature->isWalking())
|
if(creature->isWalking())
|
||||||
creature->cancelWalk();
|
creature->cancelWalk();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if(!m_walkFeedback && creature == m_localPlayer) {
|
if(creature == m_localPlayer) {
|
||||||
updateWalkPing();
|
if(!m_walkFeedback) {
|
||||||
m_walkFeedback = true;
|
updateWalkPing();
|
||||||
|
m_walkFeedback = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
creature->walk(newPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processAttackCancel()
|
void Game::processAttackCancel()
|
||||||
|
@ -176,18 +175,23 @@ void Game::processWalkCancel(Otc::Direction direction)
|
||||||
|
|
||||||
void Game::walk(Otc::Direction direction)
|
void Game::walk(Otc::Direction direction)
|
||||||
{
|
{
|
||||||
if(m_localPlayer->isFollowing()) {
|
if(!isOnline() || isDead() || !checkBotProtection())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_localPlayer->isFollowing())
|
||||||
cancelFollow();
|
cancelFollow();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isOnline() || isDead() || !checkBotProtection() || !m_localPlayer->canWalk(direction))
|
if(!m_localPlayer->canWalk(direction))
|
||||||
return;
|
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_walkPingTimer.restart();
|
||||||
|
m_walkFeedback = false;
|
||||||
|
|
||||||
switch(direction) {
|
switch(direction) {
|
||||||
case Otc::North:
|
case Otc::North:
|
||||||
|
@ -215,8 +219,6 @@ void Game::walk(Otc::Direction direction)
|
||||||
m_protocolGame->sendWalkNorthWest();
|
m_protocolGame->sendWalkNorthWest();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_walkFeedback = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::turn(Otc::Direction direction)
|
void Game::turn(Otc::Direction direction)
|
||||||
|
@ -334,6 +336,7 @@ void Game::rotate(const ThingPtr& thing)
|
||||||
m_protocolGame->sendRotateItem(thing->getPos(), thing->getId(), stackpos);
|
m_protocolGame->sendRotateItem(thing->getPos(), thing->getId(), stackpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: move this to Thing class
|
||||||
int Game::getThingStackpos(const ThingPtr& thing)
|
int Game::getThingStackpos(const ThingPtr& thing)
|
||||||
{
|
{
|
||||||
// thing is at map
|
// thing is at map
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
// walk related
|
// walk related
|
||||||
void walk(Otc::Direction direction);
|
void walk(Otc::Direction direction);
|
||||||
|
void forceWalk(Otc::Direction direction);
|
||||||
void turn(Otc::Direction direction);
|
void turn(Otc::Direction direction);
|
||||||
|
|
||||||
// item related
|
// item related
|
||||||
|
|
|
@ -25,79 +25,20 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
|
||||||
LocalPlayer::LocalPlayer()
|
void LocalPlayer::preWalk(Otc::Direction direction)
|
||||||
{
|
{
|
||||||
m_clientWalking = false;
|
// we're not walking, so start a client walk.
|
||||||
m_nextWalkDirection = Otc::InvalidDirection;
|
Position newPos = m_pos + Position::getPosFromDirection(direction);
|
||||||
}
|
walk(m_pos, newPos, true);
|
||||||
|
|
||||||
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.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocalPlayer::canWalk(Otc::Direction direction)
|
bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||||
{
|
{
|
||||||
if(m_walking) {
|
if(m_walking || (m_preWalking && g_clock.ticksElapsed(m_walkEnd) < 1000))
|
||||||
if(direction != m_direction && m_nextWalkDirection != direction)
|
|
||||||
m_nextWalkDirection = direction;
|
|
||||||
else if(direction == m_direction && m_nextWalkDirection != Otc::InvalidDirection)
|
|
||||||
m_nextWalkDirection = Otc::InvalidDirection;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
Position newPos = m_position + Position::getPosFromDirection(direction);
|
// check for blockable tiles in the walk direction
|
||||||
TilePtr tile = g_map.getTile(newPos);
|
TilePtr tile = g_map.getTile(m_pos + Position::getPosFromDirection(direction));
|
||||||
if(!tile->isWalkable()) {
|
if(!tile->isWalkable()) {
|
||||||
g_game.processTextMessage("statusSmall", "Sorry, not possible.");
|
g_game.processTextMessage("statusSmall", "Sorry, not possible.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -108,11 +49,13 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||||
|
|
||||||
void LocalPlayer::setAttackingCreature(const CreaturePtr& creature)
|
void LocalPlayer::setAttackingCreature(const CreaturePtr& creature)
|
||||||
{
|
{
|
||||||
|
// clear current attacking creature
|
||||||
if(m_attackingCreature) {
|
if(m_attackingCreature) {
|
||||||
m_attackingCreature->hideStaticSquare();
|
m_attackingCreature->hideStaticSquare();
|
||||||
m_attackingCreature = nullptr;
|
m_attackingCreature = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the new attacking creature
|
||||||
if(creature) {
|
if(creature) {
|
||||||
creature->showStaticSquare(Fw::red);
|
creature->showStaticSquare(Fw::red);
|
||||||
m_attackingCreature = creature;
|
m_attackingCreature = creature;
|
||||||
|
@ -121,11 +64,13 @@ void LocalPlayer::setAttackingCreature(const CreaturePtr& creature)
|
||||||
|
|
||||||
void LocalPlayer::setFollowingCreature(const CreaturePtr& creature)
|
void LocalPlayer::setFollowingCreature(const CreaturePtr& creature)
|
||||||
{
|
{
|
||||||
|
// clear current following creature
|
||||||
if(m_followingCreature) {
|
if(m_followingCreature) {
|
||||||
m_followingCreature->hideStaticSquare();
|
m_followingCreature->hideStaticSquare();
|
||||||
m_followingCreature = nullptr;
|
m_followingCreature = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the new attacking creature
|
||||||
if(creature) {
|
if(creature) {
|
||||||
creature->showStaticSquare(Fw::green);
|
creature->showStaticSquare(Fw::green);
|
||||||
m_followingCreature = creature;
|
m_followingCreature = creature;
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
class LocalPlayer : public Player
|
class LocalPlayer : public Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LocalPlayer();
|
|
||||||
|
|
||||||
void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); }
|
void setCanReportBugs(uint8 canReportBugs) { m_canReportBugs = (canReportBugs != 0); }
|
||||||
void setSkill(Otc::Skill skill, Otc::SkillType skillType, int value) { m_skills[skill][skillType] = value; }
|
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; }
|
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]; }
|
double getStatistic(Otc::Statistic statistic) { return m_statistics[statistic]; }
|
||||||
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
|
CreaturePtr getAttackingCreature() { return m_attackingCreature; }
|
||||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||||
Otc::Direction getNextWalkDirection() { return m_nextWalkDirection; }
|
|
||||||
Otc::PlayerIcons getIcons() { return m_icons; }
|
Otc::PlayerIcons getIcons() { return m_icons; }
|
||||||
|
|
||||||
bool isAttacking() { return m_attackingCreature != nullptr; }
|
bool isAttacking() { return m_attackingCreature != nullptr; }
|
||||||
bool isFollowing() { return m_followingCreature != nullptr; }
|
bool isFollowing() { return m_followingCreature != nullptr; }
|
||||||
|
|
||||||
void clientWalk(Otc::Direction direction);
|
void preWalk(Otc::Direction direction);
|
||||||
void walk(const Position& position, bool inverse);
|
|
||||||
void cancelWalk(Otc::Direction direction, bool force = false);
|
|
||||||
bool canWalk(Otc::Direction direction);
|
bool canWalk(Otc::Direction direction);
|
||||||
|
|
||||||
LocalPlayerPtr asLocalPlayer() { return std::static_pointer_cast<LocalPlayer>(shared_from_this()); }
|
LocalPlayerPtr asLocalPlayer() { return std::static_pointer_cast<LocalPlayer>(shared_from_this()); }
|
||||||
|
|
||||||
double getLevel() { return getStatistic(Otc::Level); }
|
double getLevel() { return getStatistic(Otc::Level); }
|
||||||
|
//TODO: more gets
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_canReportBugs;
|
bool m_canReportBugs;
|
||||||
bool m_clientWalking;
|
|
||||||
Otc::Direction m_nextWalkDirection;
|
|
||||||
CreaturePtr m_attackingCreature, m_followingCreature;
|
CreaturePtr m_attackingCreature, m_followingCreature;
|
||||||
Otc::PlayerIcons m_icons;
|
Otc::PlayerIcons m_icons;
|
||||||
int m_skills[Otc::LastSkill][Otc::LastSkillType];
|
int m_skills[Otc::LastSkill][Otc::LastSkillType];
|
||||||
|
|
|
@ -35,7 +35,7 @@ Missile::Missile() : Thing()
|
||||||
void Missile::draw(const Point& p, const Rect&)
|
void Missile::draw(const Point& p, const Rect&)
|
||||||
{
|
{
|
||||||
float time = (g_clock.ticks() - m_startTicks) / m_duration;
|
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)
|
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_yPattern = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_position = fromPosition;
|
m_pos = fromPosition;
|
||||||
m_positionDelta = toPosition - fromPosition;
|
m_posDelta = toPosition - fromPosition;
|
||||||
m_startTicks = g_clock.ticks();
|
m_startTicks = g_clock.ticks();
|
||||||
m_duration = 150 * std::sqrt(Point(m_positionDelta.x, m_positionDelta.y).length());
|
m_duration = 150 * std::sqrt(Point(m_posDelta.x, m_posDelta.y).length());
|
||||||
m_positionDelta.x *= Map::NUM_TILE_PIXELS;
|
m_posDelta.x *= Map::NUM_TILE_PIXELS;
|
||||||
m_positionDelta.y *= Map::NUM_TILE_PIXELS;
|
m_posDelta.y *= Map::NUM_TILE_PIXELS;
|
||||||
|
|
||||||
// schedule removal
|
// schedule removal
|
||||||
auto self = asMissile();
|
auto self = asMissile();
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ticks_t m_startTicks;
|
ticks_t m_startTicks;
|
||||||
Position m_positionDelta;
|
Position m_posDelta;
|
||||||
float m_duration;
|
float m_duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,14 @@ public:
|
||||||
virtual void draw(const Point& p, const Rect&) = 0;
|
virtual void draw(const Point& p, const Rect&) = 0;
|
||||||
|
|
||||||
void setId(uint32 id);
|
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; }
|
uint32 getId() const { return m_id; }
|
||||||
Position getPos() const { return m_position; }
|
Position getPos() const { return m_pos; }
|
||||||
int getStackPriority();
|
int getStackPriority();
|
||||||
virtual ThingType *getType();
|
virtual ThingType *getType();
|
||||||
int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; }
|
int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; }
|
||||||
|
int getGroundSpeed() { return m_type->parameters[ThingType::GroundSpeed]; }
|
||||||
|
|
||||||
void setXPattern(int xPattern) { m_xPattern = xPattern; }
|
void setXPattern(int xPattern) { m_xPattern = xPattern; }
|
||||||
void setYPattern(int yPattern) { m_yPattern = yPattern; }
|
void setYPattern(int yPattern) { m_yPattern = yPattern; }
|
||||||
|
@ -87,7 +88,7 @@ protected:
|
||||||
void internalDraw(const Point& p, int layer);
|
void internalDraw(const Point& p, int layer);
|
||||||
|
|
||||||
uint32 m_id;
|
uint32 m_id;
|
||||||
Position m_position;
|
Position m_pos;
|
||||||
ThingType *m_type;
|
ThingType *m_type;
|
||||||
|
|
||||||
int m_xPattern, m_yPattern, m_zPattern, m_animation;
|
int m_xPattern, m_yPattern, m_zPattern, m_animation;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
Tile::Tile(const Position& position)
|
Tile::Tile(const Position& position)
|
||||||
{
|
{
|
||||||
m_drawElevation = 0;
|
m_drawElevation = 0;
|
||||||
m_position = position;
|
m_pos = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tile::draw(const Point& p, const Rect& visibleRect)
|
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
|
//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 xi = -1; xi <= 1; ++xi) {
|
||||||
for(int yi = -1; yi <= 1; ++yi) {
|
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();
|
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 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);
|
Rect thisTileRect(p.x, p.y, 32, 32);
|
||||||
|
@ -197,6 +197,14 @@ ItemPtr Tile::getGround()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Tile::getGroundSpeed()
|
||||||
|
{
|
||||||
|
int groundSpeed = 100;
|
||||||
|
if(ItemPtr ground = getGround())
|
||||||
|
groundSpeed = ground->getGroundSpeed();
|
||||||
|
return groundSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
ThingPtr Tile::getTopLookThing()
|
ThingPtr Tile::getTopLookThing()
|
||||||
{
|
{
|
||||||
if(isEmpty())
|
if(isEmpty())
|
||||||
|
|
|
@ -50,10 +50,11 @@ public:
|
||||||
CreaturePtr getTopCreature();
|
CreaturePtr getTopCreature();
|
||||||
ThingPtr getTopMultiUseThing();
|
ThingPtr getTopMultiUseThing();
|
||||||
|
|
||||||
const Position& getPos() { return m_position; }
|
const Position& getPos() { return m_pos; }
|
||||||
int getDrawElevation() { return m_drawElevation; }
|
int getDrawElevation() { return m_drawElevation; }
|
||||||
std::vector<CreaturePtr> getCreatures();
|
std::vector<CreaturePtr> getCreatures();
|
||||||
ItemPtr getGround();
|
ItemPtr getGround();
|
||||||
|
int getGroundSpeed();
|
||||||
bool isWalkable();
|
bool isWalkable();
|
||||||
bool isFullGround();
|
bool isFullGround();
|
||||||
bool isFullyOpaque();
|
bool isFullyOpaque();
|
||||||
|
@ -67,7 +68,7 @@ public:
|
||||||
private:
|
private:
|
||||||
std::vector<EffectPtr> m_effects; // Leave this outside m_things because it has no stackpos.
|
std::vector<EffectPtr> m_effects; // Leave this outside m_things because it has no stackpos.
|
||||||
std::vector<ThingPtr> m_things;
|
std::vector<ThingPtr> m_things;
|
||||||
Position m_position;
|
Position m_pos;
|
||||||
int m_drawElevation;
|
int m_drawElevation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,8 @@ void OTClient::registerLuaFunctions()
|
||||||
g_lua.bindClassStaticFunction<Game>("open", std::bind(&Game::open, &g_game, _1, _2));
|
g_lua.bindClassStaticFunction<Game>("open", std::bind(&Game::open, &g_game, _1, _2));
|
||||||
g_lua.bindClassStaticFunction<Game>("use", std::bind(&Game::use, &g_game, _1));
|
g_lua.bindClassStaticFunction<Game>("use", std::bind(&Game::use, &g_game, _1));
|
||||||
g_lua.bindClassStaticFunction<Game>("useWith", std::bind(&Game::useWith, &g_game, _1, _2));
|
g_lua.bindClassStaticFunction<Game>("useWith", std::bind(&Game::useWith, &g_game, _1, _2));
|
||||||
|
g_lua.bindClassStaticFunction<Game>("walk", std::bind(&Game::walk, &g_game, _1));
|
||||||
|
g_lua.bindClassStaticFunction<Game>("forceWalk", std::bind(&Game::forceWalk, &g_game, _1));
|
||||||
g_lua.bindClassStaticFunction<Game>("attack", std::bind(&Game::attack, &g_game, _1));
|
g_lua.bindClassStaticFunction<Game>("attack", std::bind(&Game::attack, &g_game, _1));
|
||||||
g_lua.bindClassStaticFunction<Game>("cancelAttack", std::bind(&Game::cancelAttack, &g_game));
|
g_lua.bindClassStaticFunction<Game>("cancelAttack", std::bind(&Game::cancelAttack, &g_game));
|
||||||
g_lua.bindClassStaticFunction<Game>("follow", std::bind(&Game::follow, &g_game, _1));
|
g_lua.bindClassStaticFunction<Game>("follow", std::bind(&Game::follow, &g_game, _1));
|
||||||
|
|
|
@ -419,13 +419,11 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_game.processCreatureMove(creature, oldPos, newPos);
|
|
||||||
|
|
||||||
// update map tiles
|
// update map tiles
|
||||||
g_map.removeThing(thing);
|
g_map.removeThing(thing);
|
||||||
g_map.addThing(thing, newPos);
|
g_map.addThing(thing, newPos);
|
||||||
|
|
||||||
//g_game.processCreatureMove(creature, oldPos, newPos);
|
g_game.processCreatureMove(creature, oldPos, newPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::parseOpenContainer(InputMessage& msg)
|
void ProtocolGame::parseOpenContainer(InputMessage& msg)
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
#include <framework/ui/uilineedit.h>
|
#include <framework/ui/uilineedit.h>
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
|
||||||
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;
|
return true;
|
||||||
|
|
||||||
UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(getParent()->recursiveGetChildById("consoleLineEdit"));
|
UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(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 true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UIGame::onKeyText(const std::string& keyText)
|
||||||
|
{
|
||||||
|
if(UIWidget::onKeyText(keyText))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(getParent()->recursiveGetChildById("consoleLineEdit"));
|
||||||
|
chatLineEdit->appendText(keyText);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
class UIGame : public UIWidget
|
class UIGame : public UIWidget
|
||||||
{
|
{
|
||||||
protected:
|
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
|
#endif
|
||||||
|
|
|
@ -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 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;
|
return std::abs(x-pos.x) <= xdif && std::abs(y-pos.y) <= ydif && std::abs(pos.z-z) <= zdif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue