walk and key event system rework with some regressions

This commit is contained in:
Eduardo Bart
2012-01-15 19:19:52 -02:00
parent 9ec40f016d
commit 44a20222bb
52 changed files with 542 additions and 346 deletions

View File

@@ -228,6 +228,8 @@ namespace Fw
enum InputEventType {
NoInputEvent = 0,
KeyTextInputEvent,
KeyDownInputEvent,
KeyPressInputEvent,
KeyReleaseInputEvent,
MousePressInputEvent,

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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));

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -82,7 +82,6 @@ private:
HGLRC m_glContext;
bool m_maximized;
Size m_minimumSize;
std::map<int, Fw::Key> m_keyMap;
};
#endif

View File

@@ -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()

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -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;

View File

@@ -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

View File

@@ -56,6 +56,7 @@ public:
// walk related
void walk(Otc::Direction direction);
void forceWalk(Otc::Direction direction);
void turn(Otc::Direction direction);
// item related

View File

@@ -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;

View File

@@ -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];

View File

@@ -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();

View File

@@ -47,7 +47,7 @@ public:
private:
ticks_t m_startTicks;
Position m_positionDelta;
Position m_posDelta;
float m_duration;
};

View File

@@ -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;

View File

@@ -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())

View File

@@ -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;
};

View File

@@ -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));

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}