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