diff --git a/shader/hue.frag b/shader/hue.frag index 405c91b..416ee9b 100644 --- a/shader/hue.frag +++ b/shader/hue.frag @@ -29,11 +29,7 @@ void main () /* Make the user's adjustments */ hue += hueAdjust; - /* Remember old I and color */ - float IOriginal = I; - vec4 coOriginal = color; - - /* Convert back to YIQ */ + // Convert back to YIQ Q = chroma * sin (hue); I = chroma * cos (hue); @@ -44,5 +40,5 @@ void main () color.b = dot (yIQ, kYIQToB); /* Save the result */ - gl_FragColor = (IOriginal == 0.0) ? coOriginal : color; + gl_FragColor = color; } diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 37b3984..fa499ad 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -51,8 +51,6 @@ "Operation not supported for mega surfaces"); \ } -#define OUTLINE_SIZE 1 - /* Normalize (= ensure width and * height are positive) */ static IntRect normalizedRect(const IntRect &rect) @@ -944,7 +942,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) TTF_Font *font = p->font->getSdlFont(); const Color &fontColor = p->font->getColor(); - const Color &outColor = p->font->getOutColor(); SDL_Color c = fontColor.toSDLColor(); c.a = 255; @@ -960,33 +957,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888); - if (p->font->getShadow()) + // While real outlining is not yet here, use shadow + // as a replacement to at least make text legible + if (p->font->getShadow() || p->font->getOutline()) applyShadow(txtSurf, *p->format, c); - /* outline using TTF_Outline and blending it together with SDL_BlitSurface - * FIXME: outline is forced to have the same opacity as the font color */ - if (p->font->getOutline()) { - SDL_Color co = outColor.toSDLColor(); - co.a = 255; - SDL_Surface *outline; - /* set the next font render to render the outline */ - TTF_SetFontOutline(font, OUTLINE_SIZE); - if (shState->rtData().config.solidFonts) - outline = TTF_RenderUTF8_Solid(font, str, co); - else - outline = TTF_RenderUTF8_Blended(font, str, co); - - p->ensureFormat(outline, SDL_PIXELFORMAT_ABGR8888); - SDL_Rect outRect = {OUTLINE_SIZE, OUTLINE_SIZE, txtSurf->w, txtSurf->h}; - - SDL_SetSurfaceBlendMode(txtSurf, SDL_BLENDMODE_BLEND); - SDL_BlitSurface(txtSurf, NULL, outline, &outRect); - SDL_FreeSurface(txtSurf); - txtSurf = outline; - /* reset outline to 0 */ - TTF_SetFontOutline(font, 0); - } - int alignX = rect.x; switch (align) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 6000dad..478eb8b 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -38,7 +38,7 @@ uint8_t EventThread::keyStates[] = { false }; EventThread::JoyState EventThread::joyState = { - { 0 }, { false } + { 0 }, { 0 }, { false } }; EventThread::MouseState EventThread::mouseState = @@ -274,8 +274,12 @@ void EventThread::process(RGSSThreadData &rtData) joyState.buttons[event.jbutton.button] = false; break; + case SDL_JOYHATMOTION : + joyState.hats[event.jhat.hat] = event.jhat.value; + break; + case SDL_JOYAXISMOTION : - joyState.axis[event.jaxis.axis] = event.jaxis.value; + joyState.axes[event.jaxis.axis] = event.jaxis.value; break; case SDL_JOYDEVICEADDED : diff --git a/src/eventthread.h b/src/eventthread.h index 15d4f63..9f7f508 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -46,7 +46,8 @@ public: struct JoyState { - int axis[256]; + int axes[256]; + uint8_t hats[256]; bool buttons[256]; }; diff --git a/src/input.cpp b/src/input.cpp index 1cae58a..d7978bd 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -133,7 +133,7 @@ struct JsAxisBinding : public Binding bool sourceActive() const { - int val = EventThread::joyState.axis[source]; + int val = EventThread::joyState.axes[source]; if (dir == Negative) return val < -JAXIS_THRESHOLD; @@ -150,6 +150,34 @@ struct JsAxisBinding : public Binding AxisDir dir; }; +/* Joystick hat binding */ +struct JsHatBinding : public Binding +{ + JsHatBinding() {} + + JsHatBinding(uint8_t source, + uint8_t pos, + Input::ButtonCode target) + : Binding(target), + source(source), + pos(pos) + {} + + bool sourceActive() const + { + /* For a diagonal input accept it as an input for both the axes */ + return (pos & EventThread::joyState.hats[source]) != 0; + } + + bool sourceRepeatable() const + { + return true; + } + + uint8_t source; + uint8_t pos; +}; + /* Mouse button binding */ struct MsBinding : public Binding { @@ -241,6 +269,7 @@ struct InputPrivate std::vector kbStatBindings; std::vector kbBindings; std::vector jsABindings; + std::vector jsHBindings; std::vector jsBBindings; std::vector msBindings; @@ -348,6 +377,7 @@ struct InputPrivate { kbBindings.clear(); jsABindings.clear(); + jsHBindings.clear(); jsBBindings.clear(); for (size_t i = 0; i < d.size(); ++i) @@ -381,6 +411,16 @@ struct InputPrivate break; } + case JHat : + { + JsHatBinding bind; + bind.source = src.d.jh.hat; + bind.pos = src.d.jh.pos; + bind.target = desc.target; + jsHBindings.push_back(bind); + + break; + } case JButton : { JsButtonBinding bind; @@ -402,6 +442,7 @@ struct InputPrivate appendBindings(kbBindings); appendBindings(jsABindings); + appendBindings(jsHBindings); appendBindings(jsBBindings); } diff --git a/src/keybindings.cpp b/src/keybindings.cpp index 6f54f9c..49d2a71 100644 --- a/src/keybindings.cpp +++ b/src/keybindings.cpp @@ -129,6 +129,20 @@ static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::Button d.push_back(desc); } +static void addHatBinding(BDescVec &d, uint8_t hat, uint8_t pos, Input::ButtonCode target) +{ + SourceDesc src; + src.type = JHat; + src.d.jh.hat = hat; + src.d.jh.pos = pos; + + BindingDesc desc; + desc.src = src; + desc.target = target; + + d.push_back(desc); +} + BDescVec genDefaultBindings(const Config &conf) { BDescVec d; @@ -150,11 +164,16 @@ BDescVec genDefaultBindings(const Config &conf) addAxisBinding(d, 0, Positive, Input::Right); addAxisBinding(d, 1, Negative, Input::Up ); addAxisBinding(d, 1, Positive, Input::Down ); + + addHatBinding(d, 0, SDL_HAT_LEFT, Input::Left ); + addHatBinding(d, 0, SDL_HAT_RIGHT, Input::Right); + addHatBinding(d, 0, SDL_HAT_UP, Input::Up ); + addHatBinding(d, 0, SDL_HAT_DOWN, Input::Down ); return d; } -#define FORMAT_VER 1 +#define FORMAT_VER 2 struct Header { @@ -247,6 +266,10 @@ static bool verifyDesc(const BindingDesc &desc) return src.d.scan < SDL_NUM_SCANCODES; case JButton: return true; + case JHat: + /* Only accept single directional binds */ + return src.d.jh.pos == SDL_HAT_LEFT || src.d.jh.pos == SDL_HAT_RIGHT || + src.d.jh.pos == SDL_HAT_UP || src.d.jh.pos == SDL_HAT_DOWN; case JAxis: return src.d.ja.dir == Negative || src.d.ja.dir == Positive; default: diff --git a/src/keybindings.h b/src/keybindings.h index 9bd6c43..3d437c9 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -25,6 +25,7 @@ #include "input.h" #include +#include #include #include #include @@ -40,7 +41,8 @@ enum SourceType Invalid, Key, JButton, - JAxis + JAxis, + JHat }; struct SourceDesc @@ -60,6 +62,13 @@ struct SourceDesc /* Joystick axis direction */ AxisDir dir; } ja; + struct + { + /* Joystick axis index */ + uint8_t hat; + /* Joystick axis direction */ + uint8_t pos; + } jh; } d; bool operator==(const SourceDesc &o) const @@ -77,6 +86,8 @@ struct SourceDesc return d.jb == o.d.jb; case JAxis: return (d.ja.axis == o.d.ja.axis) && (d.ja.dir == o.d.ja.dir); + case JHat: + return (d.jh.hat == o.d.jh.hat) && (d.jh.pos == o.d.jh.pos); default: assert(!"unreachable"); return false; diff --git a/src/main.cpp b/src/main.cpp index bdcd7ad..6185e58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -321,6 +321,11 @@ int main(int argc, char *argv[]) /* Clean up any remainin events */ eventThread.cleanup(); + /* Store key bindings */ + BDescVec keyBinds; + rtData.bindingUpdateMsg.get(keyBinds); + storeBindings(keyBinds, rtData.config); + Debug() << "Shutting down."; SDL_DestroyWindow(win); diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index a734ffa..4a2577c 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -81,6 +81,7 @@ static elementsN(vButtons); std::string sourceDescString(const SourceDesc &src) { char buf[128]; + char pos; switch (src.type) { @@ -104,6 +105,32 @@ std::string sourceDescString(const SourceDesc &src) snprintf(buf, sizeof(buf), "JS %d", src.d.jb); return buf; + case JHat: + switch(src.d.jh.pos) + { + case SDL_HAT_UP: + pos = 'U'; + break; + + case SDL_HAT_DOWN: + pos = 'D'; + break; + + case SDL_HAT_LEFT: + pos = 'L'; + break; + + case SDL_HAT_RIGHT: + pos = 'R'; + break; + + default: + pos = '-'; + } + snprintf(buf, sizeof(buf), "Hat %d:%c", + src.d.jh.hat, pos); + return buf; + case JAxis: snprintf(buf, sizeof(buf), "Axis %d%c", src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+'); @@ -616,6 +643,21 @@ struct SettingsMenuPrivate desc.d.jb = event.jbutton.button; break; + case SDL_JOYHATMOTION: + { + int v = event.jhat.value; + + /* Only register if single directional input */ + if (v != SDL_HAT_LEFT && v != SDL_HAT_RIGHT && + v != SDL_HAT_UP && v != SDL_HAT_DOWN) + return true; + + desc.type = JHat; + desc.d.jh.hat = event.jhat.hat; + desc.d.jh.pos = v; + break; + } + case SDL_JOYAXISMOTION: { int v = event.jaxis.value; @@ -678,9 +720,6 @@ struct SettingsMenuPrivate rtData.bindingUpdateMsg.post(binds); - /* Store the key bindings to disk as well to prevent config loss */ - storeBindings(binds, rtData.config); - destroyReq = true; } @@ -1011,6 +1050,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event) case SDL_JOYBUTTONDOWN : case SDL_JOYBUTTONUP : + case SDL_JOYHATMOTION : case SDL_JOYAXISMOTION : if (!p->hasFocus) return false; @@ -1087,6 +1127,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event) } case SDL_JOYBUTTONDOWN: + case SDL_JOYHATMOTION: case SDL_JOYAXISMOTION: if (p->state != AwaitingInput) return true;