]> git.localhorst.tv Git - blank.git/commitdiff
make buttons configurable
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 14 Aug 2015 12:16:56 +0000 (14:16 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 14 Aug 2015 14:18:29 +0000 (16:18 +0200)
running
src/app/Environment.hpp
src/app/WorldState.hpp
src/app/runtime.cpp
src/io/token.cpp
src/ui/Keymap.hpp [new file with mode: 0644]
src/ui/ui.cpp

diff --git a/running b/running
index 26a0f9e8112809c27ccfbff423790ba7f2054203..8638f4338144b0b9c10e9326fafa1f87873d296d 100644 (file)
--- a/running
+++ b/running
@@ -88,3 +88,10 @@ Press N to toggle player/world collision.
 F1 toggles UI rendering.
 F3 toggles a display telling how long on average it takes to compute a frame.
 F4 toggles audio.
+
+Controls are interpreted by scancode, meaning you don't have to break your
+fingers when you're on an AZERTY. WSAD will be ZSQD there and the above
+description is just wrong.
+
+Also I've added a plethora of alternate keys that can be used, like arrow
+keys for movement, ins/del for placing/removing blocks, etc.
index b9dcc2900f97760f92e6948a7434619252756330..4c935d815e2f4a13483452e791a203dcfce31db7 100644 (file)
@@ -6,6 +6,7 @@
 #include "StateControl.hpp"
 #include "../audio/Audio.hpp"
 #include "../graphics/Viewport.hpp"
+#include "../ui/Keymap.hpp"
 
 #include <string>
 
@@ -21,6 +22,7 @@ struct Environment {
        Window &window;
 
        Assets assets;
+       Keymap keymap;
        FrameCounter counter;
 
        StateControl state;
index 6ab613f85e88634b6dd03bf276964276330a649d..04bf6a84a8100a744018e0f0ba7036a87dff874f 100644 (file)
@@ -31,6 +31,7 @@ public:
        void Render(Viewport &) override;
 
        World &GetWorld() noexcept { return world; }
+       Interface &GetInterface() noexcept { return interface; }
 
 private:
        Environment &env;
index 72a51da2b6eef53e7e376e3d60693bc472b28dde..d77cf47c228fbbdbc573f1e5e26f2473f2ab00ed 100644 (file)
@@ -4,10 +4,12 @@
 #include "WorldState.hpp"
 
 #include "init.hpp"
+#include "../io/filesystem.hpp"
 #include "../io/WorldSave.hpp"
 
 #include <cctype>
 #include <cstdlib>
+#include <fstream>
 #include <iostream>
 #include <SDL.h>
 
@@ -51,6 +53,7 @@ Environment::Environment(Window &win, const string &asset_path)
 , counter() {
        viewport.Clear();
        window.Flip();
+       keymap.LoadDefault();
 }
 
 
@@ -232,6 +235,16 @@ int Runtime::Execute() {
        Environment env(init.window, config.asset_path);
        env.viewport.VSync(config.vsync);
 
+       std::string keys_path = config.save_path + "keys.conf";
+       if (!is_file(keys_path)) {
+               std::ofstream file(keys_path);
+               env.keymap.Save(file);
+       } else {
+               std::ifstream file(keys_path);
+               env.keymap.Load(file);
+       }
+
+
        WorldSave save(config.save_path + config.world_name + '/');
        if (save.Exists()) {
                save.Read(config.world);
index 5e734ad573b634ed4fcf101c89735f7c64dda4b2..db5c986fb32f5e53d71272d8cb21760f2ec67e0e 100644 (file)
@@ -191,6 +191,9 @@ TokenStreamReader::TokenStreamReader(istream &in)
 
 
 bool TokenStreamReader::HasMore() {
+       if (cached) {
+               return true;
+       }
        while (in.HasMore()) {
                if (in.Next().type != Token::COMMENT) {
                        cached = true;
diff --git a/src/ui/Keymap.hpp b/src/ui/Keymap.hpp
new file mode 100644 (file)
index 0000000..e96179a
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef BLANK_UI_KEYMAP_HPP_
+#define BLANK_UI_KEYMAP_HPP_
+
+#include <iosfwd>
+#include <string>
+#include <SDL.h>
+
+
+namespace blank {
+
+class Keymap {
+
+public:
+       enum Action {
+               NONE,
+
+               MOVE_FORWARD,
+               MOVE_BACKWARD,
+               MOVE_LEFT,
+               MOVE_RIGHT,
+               MOVE_UP,
+               MOVE_DOWN,
+
+               BLOCK_FACE,
+               BLOCK_TURN,
+               BLOCK_NEXT,
+               BLOCK_PREV,
+
+               BLOCK_PLACE,
+               BLOCK_PICK,
+               BLOCK_REMOVE,
+
+               TOGGLE_COLLISION,
+               TOGGLE_AUDIO,
+               TOGGLE_VISUAL,
+               TOGGLE_DEBUG,
+
+               PRINT_BLOCK,
+               PRINT_CHUNK,
+               PRINT_LIGHT,
+               PRINT_SELECTION,
+
+               EXIT,
+       };
+
+       static constexpr unsigned int MAX_SCANCODE = 0xFF;
+       static constexpr unsigned int NUM_SCANCODES = MAX_SCANCODE + 1;
+
+public:
+       Keymap();
+
+       void Map(SDL_Scancode scancode, Action);
+       Action Lookup(SDL_Scancode scancode);
+       Action Lookup(const SDL_Keysym &s) { return Lookup(s.scancode); }
+       Action Lookup(const SDL_KeyboardEvent &e) { return Lookup(e.keysym); }
+
+       void LoadDefault();
+
+       void Load(std::istream &);
+       void Save(std::ostream &);
+
+       static const char *ActionToString(Action);
+       static Action StringToAction(const std::string &);
+
+private:
+       Action codemap[NUM_SCANCODES];
+
+};
+
+}
+
+#endif
index 6dfe5160dd87417204037e4dad75ca8c5903e658..ef005f6dea778ec8f243a8087e7167c0368f59f1 100644 (file)
@@ -1,5 +1,6 @@
 #include "HUD.hpp"
 #include "Interface.hpp"
+#include "Keymap.hpp"
 
 #include "../app/Assets.hpp"
 #include "../app/Environment.hpp"
@@ -8,6 +9,7 @@
 #include "../audio/Audio.hpp"
 #include "../graphics/Font.hpp"
 #include "../graphics/Viewport.hpp"
+#include "../io/TokenStreamReader.hpp"
 #include "../model/shapes.hpp"
 #include "../world/World.hpp"
 
@@ -140,84 +142,110 @@ Interface::Interface(
 void Interface::HandlePress(const SDL_KeyboardEvent &event) {
        if (config.keyboard_disabled) return;
 
-       switch (event.keysym.sym) {
-               case SDLK_w:
+       switch (env.keymap.Lookup(event)) {
+               case Keymap::MOVE_FORWARD:
                        rev.z = 1;
                        break;
-               case SDLK_s:
+               case Keymap::MOVE_BACKWARD:
                        fwd.z = 1;
                        break;
-               case SDLK_a:
+               case Keymap::MOVE_LEFT:
                        rev.x = 1;
                        break;
-               case SDLK_d:
+               case Keymap::MOVE_RIGHT:
                        fwd.x = 1;
                        break;
-               case SDLK_SPACE:
+               case Keymap::MOVE_UP:
                        fwd.y = 1;
                        break;
-               case SDLK_LSHIFT:
+               case Keymap::MOVE_DOWN:
                        rev.y = 1;
                        break;
 
-               case SDLK_q:
+               case Keymap::BLOCK_FACE:
                        FaceBlock();
                        break;
-               case SDLK_e:
+               case Keymap::BLOCK_TURN:
                        TurnBlock();
                        break;
+               case Keymap::BLOCK_NEXT:
+                       SelectNext();
+                       break;
+               case Keymap::BLOCK_PREV:
+                       SelectPrevious();
+                       break;
+
+               case Keymap::BLOCK_PLACE:
+                       PlaceBlock();
+                       break;
+               case Keymap::BLOCK_PICK:
+                       PickBlock();
+                       break;
+               case Keymap::BLOCK_REMOVE:
+                       RemoveBlock();
+                       break;
 
-               case SDLK_n:
+               case Keymap::TOGGLE_COLLISION:
                        ToggleCollision();
                        break;
 
-               case SDLK_b:
+               case Keymap::PRINT_BLOCK:
                        PrintBlockInfo();
                        break;
-               case SDLK_c:
+               case Keymap::PRINT_CHUNK:
                        PrintChunkInfo();
                        break;
-               case SDLK_l:
+               case Keymap::PRINT_LIGHT:
                        PrintLightInfo();
                        break;
-               case SDLK_p:
+               case Keymap::PRINT_SELECTION:
                        PrintSelectionInfo();
                        break;
 
-               case SDLK_F1:
+               case Keymap::TOGGLE_VISUAL:
                        ToggleVisual();
                        break;
-               case SDLK_F3:
+               case Keymap::TOGGLE_DEBUG:
                        ToggleDebug();
                        break;
-               case SDLK_F4:
+               case Keymap::TOGGLE_AUDIO:
                        ToggleAudio();
                        break;
+
+               case Keymap::EXIT:
+                       env.state.Pop();
+                       break;
+
+               default:
+                       break;
        }
 }
 
 void Interface::HandleRelease(const SDL_KeyboardEvent &event) {
        if (config.keyboard_disabled) return;
 
-       switch (event.keysym.sym) {
-               case SDLK_w:
+       switch (env.keymap.Lookup(event)) {
+               case Keymap::MOVE_FORWARD:
                        rev.z = 0;
                        break;
-               case SDLK_s:
+               case Keymap::MOVE_BACKWARD:
                        fwd.z = 0;
                        break;
-               case SDLK_a:
+               case Keymap::MOVE_LEFT:
                        rev.x = 0;
                        break;
-               case SDLK_d:
+               case Keymap::MOVE_RIGHT:
                        fwd.x = 0;
                        break;
-               case SDLK_SPACE:
+               case Keymap::MOVE_UP:
                        fwd.y = 0;
                        break;
-               case SDLK_LSHIFT:
+               case Keymap::MOVE_DOWN:
                        rev.y = 0;
                        break;
+
+               default:
+                       break;
        }
 }
 
@@ -555,4 +583,217 @@ void Interface::Render(Viewport &viewport) noexcept {
        hud.Render(viewport);
 }
 
+
+Keymap::Keymap()
+: codemap{ NONE } {
+
+}
+
+void Keymap::Map(SDL_Scancode scancode, Action action) {
+       if (scancode > MAX_SCANCODE) {
+               throw std::runtime_error("refusing to map scancode: too damn high");
+       }
+       codemap[scancode] = action;
+}
+
+Keymap::Action Keymap::Lookup(SDL_Scancode scancode) {
+       if (scancode < NUM_SCANCODES) {
+               return codemap[scancode];
+       } else {
+               return NONE;
+       }
+}
+
+
+void Keymap::LoadDefault() {
+       Map(SDL_SCANCODE_UP, MOVE_FORWARD);
+       Map(SDL_SCANCODE_W, MOVE_FORWARD);
+       Map(SDL_SCANCODE_DOWN, MOVE_BACKWARD);
+       Map(SDL_SCANCODE_S, MOVE_BACKWARD);
+       Map(SDL_SCANCODE_LEFT, MOVE_LEFT);
+       Map(SDL_SCANCODE_A, MOVE_LEFT);
+       Map(SDL_SCANCODE_RIGHT, MOVE_RIGHT);
+       Map(SDL_SCANCODE_D, MOVE_RIGHT);
+       Map(SDL_SCANCODE_SPACE, MOVE_UP);
+       Map(SDL_SCANCODE_RSHIFT, MOVE_UP);
+       Map(SDL_SCANCODE_LSHIFT, MOVE_DOWN);
+       Map(SDL_SCANCODE_LCTRL, MOVE_DOWN);
+       Map(SDL_SCANCODE_RCTRL, MOVE_DOWN);
+
+       Map(SDL_SCANCODE_Q, BLOCK_FACE);
+       Map(SDL_SCANCODE_E, BLOCK_TURN);
+       Map(SDL_SCANCODE_TAB, BLOCK_NEXT);
+       Map(SDL_SCANCODE_RIGHTBRACKET, BLOCK_NEXT);
+       Map(SDL_SCANCODE_LEFTBRACKET, BLOCK_PREV);
+
+       Map(SDL_SCANCODE_INSERT, BLOCK_PLACE);
+       Map(SDL_SCANCODE_RETURN, BLOCK_PLACE);
+       Map(SDL_SCANCODE_MENU, BLOCK_PICK);
+       Map(SDL_SCANCODE_DELETE, BLOCK_REMOVE);
+       Map(SDL_SCANCODE_BACKSPACE, BLOCK_REMOVE);
+
+       Map(SDL_SCANCODE_N, TOGGLE_COLLISION);
+       Map(SDL_SCANCODE_F1, TOGGLE_VISUAL);
+       Map(SDL_SCANCODE_F3, TOGGLE_DEBUG);
+       Map(SDL_SCANCODE_F4, TOGGLE_AUDIO);
+
+       Map(SDL_SCANCODE_B, PRINT_BLOCK);
+       Map(SDL_SCANCODE_C, PRINT_CHUNK);
+       Map(SDL_SCANCODE_L, PRINT_LIGHT);
+       Map(SDL_SCANCODE_P, PRINT_SELECTION);
+
+       Map(SDL_SCANCODE_ESCAPE, EXIT);
+}
+
+
+void Keymap::Load(std::istream &is) {
+       TokenStreamReader in(is);
+       std::string key_name;
+       std::string action_name;
+       SDL_Scancode key;
+       Action action;
+       while (in.HasMore()) {
+               if (in.Peek().type == Token::STRING) {
+                       in.ReadString(key_name);
+                       key = SDL_GetScancodeFromName(key_name.c_str());
+               } else {
+                       key = SDL_Scancode(in.GetInt());
+               }
+               in.Skip(Token::EQUALS);
+               in.ReadIdentifier(action_name);
+               action = StringToAction(action_name);
+               if (in.HasMore() && in.Peek().type == Token::SEMICOLON) {
+                       in.Skip(Token::SEMICOLON);
+               }
+               Map(key, action);
+       }
+}
+
+void Keymap::Save(std::ostream &out) {
+       for (unsigned int i = 0; i < NUM_SCANCODES; ++i) {
+               if (codemap[i] == NONE) continue;
+
+               const char *str = SDL_GetScancodeName(SDL_Scancode(i));
+               if (str && *str) {
+                       out << '"';
+                       while (*str) {
+                               if (*str == '"') {
+                                       out << "\\\"";
+                               } else {
+                                       out << *str;
+                               }
+                               ++str;
+                       }
+                       out << '"';
+               } else {
+                       out << i;
+               }
+
+               out << " = " << ActionToString(codemap[i]) << std::endl;;
+       }
+}
+
+
+const char *Keymap::ActionToString(Action action) {
+       switch (action) {
+               default:
+               case NONE:
+                       return "none";
+               case MOVE_FORWARD:
+                       return "move_forward";
+               case MOVE_BACKWARD:
+                       return "move_backward";
+               case MOVE_LEFT:
+                       return "move_left";
+               case MOVE_RIGHT:
+                       return "move_right";
+               case MOVE_UP:
+                       return "move_up";
+               case MOVE_DOWN:
+                       return "move_down";
+               case BLOCK_FACE:
+                       return "block_face";
+               case BLOCK_TURN:
+                       return "block_turn";
+               case BLOCK_NEXT:
+                       return "block_next";
+               case BLOCK_PREV:
+                       return "block_prev";
+               case BLOCK_PLACE:
+                       return "block_place";
+               case BLOCK_PICK:
+                       return "block_pick";
+               case BLOCK_REMOVE:
+                       return "block_remove";
+               case TOGGLE_COLLISION:
+                       return "toggle_collision";
+               case TOGGLE_AUDIO:
+                       return "toggle_audio";
+               case TOGGLE_VISUAL:
+                       return "toggle_visual";
+               case TOGGLE_DEBUG:
+                       return "toggle_debug";
+               case PRINT_BLOCK:
+                       return "print_block";
+               case PRINT_CHUNK:
+                       return "print_chunk";
+               case PRINT_LIGHT:
+                       return "print_light";
+               case PRINT_SELECTION:
+                       return "print_selection";
+               case EXIT:
+                       return "exit";
+       }
+}
+
+Keymap::Action Keymap::StringToAction(const std::string &str) {
+       if (str == "move_forward") {
+               return MOVE_FORWARD;
+       } else if (str == "move_backward") {
+               return MOVE_BACKWARD;
+       } else if (str == "move_left") {
+               return MOVE_LEFT;
+       } else if (str == "move_right") {
+               return MOVE_RIGHT;
+       } else if (str == "move_up") {
+               return MOVE_UP;
+       } else if (str == "move_down") {
+               return MOVE_DOWN;
+       } else if (str == "block_face") {
+               return BLOCK_FACE;
+       } else if (str == "block_turn") {
+               return BLOCK_TURN;
+       } else if (str == "block_next") {
+               return BLOCK_NEXT;
+       } else if (str == "block_prev") {
+               return BLOCK_PREV;
+       } else if (str == "block_place") {
+               return BLOCK_PLACE;
+       } else if (str == "block_pick") {
+               return BLOCK_PICK;
+       } else if (str == "block_remove") {
+               return BLOCK_REMOVE;
+       } else if (str == "toggle_collision") {
+               return TOGGLE_COLLISION;
+       } else if (str == "toggle_audio") {
+               return TOGGLE_AUDIO;
+       } else if (str == "toggle_visual") {
+               return TOGGLE_VISUAL;
+       } else if (str == "toggle_debug") {
+               return TOGGLE_DEBUG;
+       } else if (str == "print_block") {
+               return PRINT_BLOCK;
+       } else if (str == "print_chunk") {
+               return PRINT_CHUNK;
+       } else if (str == "print_light") {
+               return PRINT_LIGHT;
+       } else if (str == "print_selection") {
+               return PRINT_SELECTION;
+       } else if (str == "exit") {
+               return EXIT;
+       } else {
+               return NONE;
+       }
+}
+
 }