/* ** settingsmenu.cpp ** ** This file is part of mkxp. ** ** Copyright (C) 2014 Jonas Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #include "settingsmenu.h" #include #include #include #include #include #include "keybindings.h" #include "eventthread.h" #include "font.h" #include "input.h" #include "etc-internal.h" #include "util.h" #include #include const Vec2i winSize(540, 356); const uint8_t cBgNorm = 50; const uint8_t cBgDark = 20; const uint8_t cLine = 0; const uint8_t cText = 255; const uint8_t frameWidth = 4; const uint8_t fontSize = 15; static bool pointInRect(const SDL_Rect &r, int x, int y) { return (x >= r.x && x <= r.x+r.w && y >= r.y && y <= r.y+r.h); } typedef SettingsMenuPrivate SMP; #define BTN_STRING(btn) { Input:: btn, #btn } struct VButton { Input::ButtonCode code; const char *str; } static const vButtons[] = { BTN_STRING(Up), BTN_STRING(Down), BTN_STRING(L), BTN_STRING(Left), BTN_STRING(Right), BTN_STRING(R), BTN_STRING(A), BTN_STRING(B), BTN_STRING(C), BTN_STRING(X), BTN_STRING(Y), BTN_STRING(Z) }; static elementsN(vButtons); /* Human readable string representation */ std::string sourceDescString(const SourceDesc &src) { char buf[128]; switch (src.type) { case Invalid: return std::string(); case Key: { if (src.d.scan == SDL_SCANCODE_LSHIFT) return "Shift"; SDL_Keycode key = SDL_GetKeyFromScancode(src.d.scan); const char *str = SDL_GetKeyName(key); if (*str == '\0') return "Unknown key"; else return str; } case JButton: snprintf(buf, sizeof(buf), "JS %d", src.d.jb); return buf; case JAxis: snprintf(buf, sizeof(buf), "Axis %d%c", src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+'); return buf; } assert(!"unreachable"); return ""; } struct Widget { /* Widgets have a static size and position, * defined at creation */ Widget(SMP *p, const IntRect &rect); /* Public methods take coordinates in global * window coordinates */ bool hit(int x, int y); void draw(SDL_Surface *surf); void motion(int x, int y); void leave(); void click(int x, int y, uint8_t button); protected: SMP *p; IntRect rect; /* Protected abstract methods are called with * widget-local coordinates */ virtual void drawHandler(SDL_Surface *surf) = 0; virtual void motionHandler(int x, int y) = 0; virtual void leaveHandler() = 0; virtual void clickHandler(int x, int y, uint8_t button) = 0; }; struct BindingWidget : Widget { VButton vb; /* Source slots */ SourceDesc src[4]; /* Flag indicating whether a slot source is used * for multiple button targets (red indicator) */ bool dupFlag[4]; BindingWidget(int vbIndex, SMP *p, const IntRect &rect) : Widget(p, rect), vb(vButtons[vbIndex]), hoveredCell(-1) {} void appendBindings(BDescVec &d) const; protected: int hoveredCell; void setHoveredCell(int cell); /* Get the slot cell index that contains (x,y), * or -1 if none */ int cellIndex(int x, int y) const; void drawHandler(SDL_Surface *surf); void motionHandler(int x, int y); void leaveHandler(); void clickHandler(int x, int y, uint8_t button); }; struct Button : Widget { typedef void (SMP::*Callback)(); const char *str; Callback cb; Button(SMP *p, const IntRect &rect, const char *str, Callback cb) : Widget(p, rect), str(str), cb(cb), hovered(false) {} protected: bool hovered; void setHovered(bool val); void drawHandler(SDL_Surface *surf); void motionHandler(int, int); void leaveHandler(); void clickHandler(int, int, uint8_t button); }; struct Label : Widget { const char *str; SDL_Color c; Label() : Widget(0, IntRect()) {} Label(SMP *p, const IntRect &rect, const char *str, uint8_t r, uint8_t g, uint8_t b) : Widget(p, rect), str(str) { c.r = r; c.g = g; c.b = b; c.a = 255; } void setVisible(bool val); protected: bool visible; void drawHandler(SDL_Surface *surf); void motionHandler(int, int) {} void leaveHandler() {} void clickHandler(int, int, uint8_t) {} }; enum State { Idle, AwaitingInput }; enum Justification { Left, Center }; struct SettingsMenuPrivate { State state; /* Necessary to decide which window gets to * process joystick events */ bool hasFocus; /* Tell the outer EventThread to destroy us */ bool destroyReq; /* Offset added for all draw calls */ Vec2i drawOff; SDL_Window *window; SDL_Surface *winSurf; uint32_t winID; TTF_Font *font; SDL_PixelFormat *rgb; RGSSThreadData &rtData; std::vector bWidgets; std::vector