|  | @@ -5,7 +5,9 @@
 | 
	
		
			
				|  |  |  #include <core/HashMap.h>
 | 
	
		
			
				|  |  |  #include <core/Logger.h>
 | 
	
		
			
				|  |  |  #include <core/Utility.h>
 | 
	
		
			
				|  |  | +#include <limits.h>
 | 
	
		
			
				|  |  |  #include <stdio.h>
 | 
	
		
			
				|  |  | +#include <uchar.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool dummyWindowRunHandler(void*) {
 | 
	
		
			
				|  |  |      return !shouldWindowClose();
 | 
	
	
		
			
				|  | @@ -38,10 +40,12 @@ typedef struct {
 | 
	
		
			
				|  |  |  static Clock fps = {0};
 | 
	
		
			
				|  |  |  static Clock tps = {0};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// static List<uint32> input;
 | 
	
		
			
				|  |  | -// static int inputCursor = 0;
 | 
	
		
			
				|  |  | -// static int inputLimit = 256;
 | 
	
		
			
				|  |  | -// static bool inputActive = false;
 | 
	
		
			
				|  |  | +#define INPUT_SIZE 2048
 | 
	
		
			
				|  |  | +static char input[INPUT_SIZE] = {0};
 | 
	
		
			
				|  |  | +static size_t inputLength = 0;
 | 
	
		
			
				|  |  | +static size_t inputCursor = 0;
 | 
	
		
			
				|  |  | +static size_t inputLimit = INPUT_SIZE - 1;
 | 
	
		
			
				|  |  | +static bool inputActive = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |      char name[31];
 | 
	
	
		
			
				|  | @@ -82,13 +86,8 @@ static void onButton(Button* map, int n, int key, int action) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void addError(Error& e) {
 | 
	
		
			
				|  |  | -    const char* description = nullptr;
 | 
	
		
			
				|  |  | -    int errorCode = glfwGetError(&description);
 | 
	
		
			
				|  |  | -    if(errorCode == GLFW_NO_ERROR) {
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    e.message.append(": ").append(description);
 | 
	
		
			
				|  |  | +static bool isCharSequence(size_t i) {
 | 
	
		
			
				|  |  | +    return (input[i] & 0xC0) == 0x80;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void handleInputKey(int key, int action) {
 | 
	
	
		
			
				|  | @@ -97,43 +96,66 @@ static void handleInputKey(int key, int action) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      switch(key) {
 | 
	
		
			
				|  |  |          case GLFW_KEY_BACKSPACE:
 | 
	
		
			
				|  |  | -            if(input.getLength() > inputCursor - 1 && inputCursor > 0) {
 | 
	
		
			
				|  |  | -                input.remove(inputCursor - 1);
 | 
	
		
			
				|  |  | +            if(inputLength >= inputCursor && inputCursor > 0) {
 | 
	
		
			
				|  |  | +                size_t w = 1;
 | 
	
		
			
				|  |  | +                while(inputCursor - w > 0 && isCharSequence(inputCursor - w)) {
 | 
	
		
			
				|  |  | +                    w++;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                for(size_t i = inputCursor - w; i < inputLength; i++) {
 | 
	
		
			
				|  |  | +                    input[i] = input[i + w];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                inputLength -= w;
 | 
	
		
			
				|  |  | +                inputCursor -= w;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case GLFW_KEY_LEFT: {
 | 
	
		
			
				|  |  | +            inputCursor -= inputCursor > 0;
 | 
	
		
			
				|  |  | +            while(inputCursor > 0 && isCharSequence(inputCursor)) {
 | 
	
		
			
				|  |  |                  inputCursor--;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  | -        case GLFW_KEY_LEFT: inputCursor -= inputCursor > 0; break;
 | 
	
		
			
				|  |  | -        case GLFW_KEY_RIGHT:
 | 
	
		
			
				|  |  | -            inputCursor += inputCursor < input.getLength();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        case GLFW_KEY_RIGHT: {
 | 
	
		
			
				|  |  | +            inputCursor += inputCursor < inputLength;
 | 
	
		
			
				|  |  | +            while(inputCursor < inputLength && isCharSequence(inputCursor)) {
 | 
	
		
			
				|  |  | +                inputCursor++;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void onKey(GLFWwindow*, int key, int scancode, int action, int mods) {
 | 
	
		
			
				|  |  |      (void)scancode;
 | 
	
		
			
				|  |  |      (void)mods;
 | 
	
		
			
				|  |  | -    // if(inputActive) {
 | 
	
		
			
				|  |  | -    //     handleInputKey(key, action);
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | +    if(inputActive) {
 | 
	
		
			
				|  |  | +        handleInputKey(key, action);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      onButton(keyToButton, KEYS, key, action);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*static void addUnicode(uint32 codepoint) {
 | 
	
		
			
				|  |  | -    if(input.getLength() >= inputLimit) {
 | 
	
		
			
				|  |  | +static void addUnicode(u32 c) {
 | 
	
		
			
				|  |  | +    char buffer[MB_LEN_MAX + 1] = {0};
 | 
	
		
			
				|  |  | +    mbstate_t state = {0};
 | 
	
		
			
				|  |  | +    size_t w = c32rtomb(buffer, c, &state);
 | 
	
		
			
				|  |  | +    if(w >= MB_LEN_MAX || inputLength + w >= inputLimit) {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    input.add(codepoint);
 | 
	
		
			
				|  |  | -    for(int i = input.getLength() - 1; i > inputCursor; i--) {
 | 
	
		
			
				|  |  | -        ::swap(input[i], input[i - 1]);
 | 
	
		
			
				|  |  | +    if(inputLength > 0) {
 | 
	
		
			
				|  |  | +        for(size_t i = inputLength - 1; i >= inputCursor; i--) {
 | 
	
		
			
				|  |  | +            swap(input + (i + w), input + i);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    inputCursor++;
 | 
	
		
			
				|  |  | +    memcpy(input + inputCursor, buffer, w);
 | 
	
		
			
				|  |  | +    inputLength += w;
 | 
	
		
			
				|  |  | +    inputCursor += w;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void onChar(GLFWwindow*, uint32 codepoint) {
 | 
	
		
			
				|  |  | +static void onChar(GLFWwindow*, u32 codepoint) {
 | 
	
		
			
				|  |  |      if(inputActive) {
 | 
	
		
			
				|  |  |          addUnicode(codepoint);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void onResize(GLFWwindow*, int width, int height) {
 | 
	
		
			
				|  |  |      sizeChanged = true;
 | 
	
	
		
			
				|  | @@ -153,7 +175,7 @@ static void onMouseMove(GLFWwindow*, double x, double y) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool openWindow(const WindowOptions* o) {
 | 
	
		
			
				|  |  |      if(!glfwInit()) {
 | 
	
		
			
				|  |  | -        CORE_LOG_ERROR("could not initialize GLFW");
 | 
	
		
			
				|  |  | +        LOG_ERROR("could not initialize GLFW");
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -167,13 +189,13 @@ bool openWindow(const WindowOptions* o) {
 | 
	
		
			
				|  |  |      window =
 | 
	
		
			
				|  |  |          glfwCreateWindow(o->size.data[0], o->size.data[1], o->name, m, nullptr);
 | 
	
		
			
				|  |  |      if(window == nullptr) {
 | 
	
		
			
				|  |  | -        CORE_LOG_ERROR("could not create window");
 | 
	
		
			
				|  |  | +        LOG_ERROR("could not create window");
 | 
	
		
			
				|  |  |          closeWindow();
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      size = o->size;
 | 
	
		
			
				|  |  |      glfwSetKeyCallback(window, onKey);
 | 
	
		
			
				|  |  | -    // glfwSetCharCallback(window, onChar);
 | 
	
		
			
				|  |  | +    glfwSetCharCallback(window, onChar);
 | 
	
		
			
				|  |  |      glfwSetFramebufferSizeCallback(window, onResize);
 | 
	
		
			
				|  |  |      glfwSetMouseButtonCallback(window, onMouse);
 | 
	
		
			
				|  |  |      glfwSetCursorPosCallback(window, onMouseMove);
 | 
	
	
		
			
				|  | @@ -238,7 +260,7 @@ void setWindowNanosPerTick(i64 nanos) {
 | 
	
		
			
				|  |  |  static i64 updateClock(Clock* c) {
 | 
	
		
			
				|  |  |      i64 nanos = getNanos();
 | 
	
		
			
				|  |  |      if(nanos < 0) {
 | 
	
		
			
				|  |  | -        CORE_LOG_WARNING("Cannot get nanos, using default");
 | 
	
		
			
				|  |  | +        LOG_WARNING("Cannot get nanos, using default");
 | 
	
		
			
				|  |  |          nanos = 10000000 + c->last;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      i64 diff = nanos - c->last;
 | 
	
	
		
			
				|  | @@ -343,85 +365,55 @@ float getWindowFramesPerSecond(void) {
 | 
	
		
			
				|  |  |      return (1000000000.0f * CLOCK_SIZE) / (float)fps.sum;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void Window::Input::setLimit(int l) {
 | 
	
		
			
				|  |  | -    inputLimit = l;
 | 
	
		
			
				|  |  | -    while(input.getLength() > inputLimit) {
 | 
	
		
			
				|  |  | -        input.removeBySwap(inputLimit);
 | 
	
		
			
				|  |  | +void setInputLimit(size_t limit) {
 | 
	
		
			
				|  |  | +    inputLimit = limit >= INPUT_SIZE ? INPUT_SIZE - 1 : limit;
 | 
	
		
			
				|  |  | +    if(inputLength > inputLimit) {
 | 
	
		
			
				|  |  | +        inputLength = inputLimit;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(inputCursor > inputLimit) {
 | 
	
		
			
				|  |  | +        inputCursor = inputLimit;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void Window::Input::reset() {
 | 
	
		
			
				|  |  | -    input.clear();
 | 
	
		
			
				|  |  | +void resetInput() {
 | 
	
		
			
				|  |  | +    inputLength = 0;
 | 
	
		
			
				|  |  |      inputCursor = 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void Window::Input::enable() {
 | 
	
		
			
				|  |  | +void enableInput() {
 | 
	
		
			
				|  |  |      inputActive = true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void Window::Input::disable() {
 | 
	
		
			
				|  |  | +void disableInput() {
 | 
	
		
			
				|  |  |      inputActive = false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -bool Window::Input::isEnabled() {
 | 
	
		
			
				|  |  | +bool isInputEnabled() {
 | 
	
		
			
				|  |  |      return inputActive;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static uint32 read(int& index, const char* s) {
 | 
	
		
			
				|  |  | -    if(s[index] == '\0') {
 | 
	
		
			
				|  |  | -        return '\0';
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return static_cast<uint32>(s[index++]);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static uint32 readUnicode(int& index, const char* s) {
 | 
	
		
			
				|  |  | -    uint32 c = read(index, s);
 | 
	
		
			
				|  |  | -    if((c & 0xE0) == 0xC0) {
 | 
	
		
			
				|  |  | -        c = ((c & 0x1F) << 6) | (read(index, s) & 0x3F);
 | 
	
		
			
				|  |  | -    } else if((c & 0xF0) == 0xE0) {
 | 
	
		
			
				|  |  | -        c = ((c & 0xF) << 12) | ((read(index, s) & 0x3F) << 6);
 | 
	
		
			
				|  |  | -        c |= read(index, s) & 0x3F;
 | 
	
		
			
				|  |  | -    } else if((c & 0xF8) == 0xF0) {
 | 
	
		
			
				|  |  | -        c = ((c & 0x7) << 18) | ((read(index, s) & 0x3F) << 12);
 | 
	
		
			
				|  |  | -        c |= (read(index, s) & 0x3F) << 6;
 | 
	
		
			
				|  |  | -        c |= read(index, s) & 0x3F;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return c;
 | 
	
		
			
				|  |  | +void fillInput(const char* s) {
 | 
	
		
			
				|  |  | +    resetInput();
 | 
	
		
			
				|  |  | +    snprintf(input, inputLength, "%s", s);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void Window::Input::fill(const char* s) {
 | 
	
		
			
				|  |  | -    int index = 0;
 | 
	
		
			
				|  |  | -    reset();
 | 
	
		
			
				|  |  | -    while(true) {
 | 
	
		
			
				|  |  | -        uint32 c = readUnicode(index, s);
 | 
	
		
			
				|  |  | -        if(c == '\0') {
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        addUnicode(c);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int Window::Input::getCursor() {
 | 
	
		
			
				|  |  | +size_t getInputCursor() {
 | 
	
		
			
				|  |  |      return inputCursor;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void Window::Input::setCursor(int index) {
 | 
	
		
			
				|  |  | -    if(index < 0) {
 | 
	
		
			
				|  |  | -        inputCursor = 0;
 | 
	
		
			
				|  |  | -    } else if(index > input.getLength()) {
 | 
	
		
			
				|  |  | -        inputCursor = input.getLength();
 | 
	
		
			
				|  |  | +void setInputCursor(size_t index) {
 | 
	
		
			
				|  |  | +    if(index > inputLength) {
 | 
	
		
			
				|  |  | +        inputCursor = inputLength;
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |          inputCursor = index;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const List<uint32>& Window::Input::getUnicode() {
 | 
	
		
			
				|  |  | +const char* getInputString(void) {
 | 
	
		
			
				|  |  |      return input;
 | 
	
		
			
				|  |  | -}*/
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Button coreAddButton(const char* name) {
 | 
	
		
			
				|  |  | +Button addButton(const char* name) {
 | 
	
		
			
				|  |  |      if(buttonIndex >= BUTTONS) {
 | 
	
		
			
				|  |  |          return 0;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -430,47 +422,47 @@ Button coreAddButton(const char* name) {
 | 
	
		
			
				|  |  |      return b;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void coreBindKeyToButton(Button b, int key) {
 | 
	
		
			
				|  |  | +void bindKeyToButton(Button b, int key) {
 | 
	
		
			
				|  |  |      if(key >= 0 && key < KEYS) {
 | 
	
		
			
				|  |  |          keyToButton[key] = b;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void coreBindGamepadToButton(Button b, int gamepadButton) {
 | 
	
		
			
				|  |  | +void bindGamepadToButton(Button b, int gamepadButton) {
 | 
	
		
			
				|  |  |      if(gamepadButton >= 0 && gamepadButton < GAMEPAD_BUTTONS) {
 | 
	
		
			
				|  |  |          gamepadToButton[gamepadButton] = b;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void coreBindMouseToButton(Button b, int mouseButton) {
 | 
	
		
			
				|  |  | +void bindMouseToButton(Button b, int mouseButton) {
 | 
	
		
			
				|  |  |      if(mouseButton >= 0 && mouseButton < MOUSE_BUTTONS) {
 | 
	
		
			
				|  |  |          mouseToButton[mouseButton] = b;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Vector2 coreGetLastMousePosition(void) {
 | 
	
		
			
				|  |  | +Vector2 getLastMousePosition(void) {
 | 
	
		
			
				|  |  |      return lastMousePosition;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Vector2 coreGetMousePosition(void) {
 | 
	
		
			
				|  |  | +Vector2 getMousePosition(void) {
 | 
	
		
			
				|  |  |      return mousePosition;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Vector2 coreGetLeftGamepadAxis(void) {
 | 
	
		
			
				|  |  | +Vector2 getLeftGamepadAxis(void) {
 | 
	
		
			
				|  |  |      return (Vector2){{lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_X],
 | 
	
		
			
				|  |  |                        lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]}};
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Vector2 coreGetRightGamepadAxis(void) {
 | 
	
		
			
				|  |  | +Vector2 getRightGamepadAxis(void) {
 | 
	
		
			
				|  |  |      return (Vector2){{lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X],
 | 
	
		
			
				|  |  |                        lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]}};
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -float coreGetLeftGamepadTrigger(void) {
 | 
	
		
			
				|  |  | +float getLeftGamepadTrigger(void) {
 | 
	
		
			
				|  |  |      return lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -float coreGetRightGamepadTrigger(void) {
 | 
	
		
			
				|  |  | +float getRightGamepadTrigger(void) {
 | 
	
		
			
				|  |  |      return lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -478,18 +470,18 @@ static const ButtonData* getButton(Button id) {
 | 
	
		
			
				|  |  |      return buttons + (id >= buttonIndex ? 0 : id);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -bool coreIsButtonDown(Button b) {
 | 
	
		
			
				|  |  | +bool isButtonDown(Button b) {
 | 
	
		
			
				|  |  |      return getButton(b)->downTime > 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -int coreGetButtonDownTime(Button b) {
 | 
	
		
			
				|  |  | +int getButtonDownTime(Button b) {
 | 
	
		
			
				|  |  |      return getButton(b)->downTime;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -bool coreWasButtonReleased(Button b) {
 | 
	
		
			
				|  |  | +bool wasButtonReleased(Button b) {
 | 
	
		
			
				|  |  |      return getButton(b)->released;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const char* coreGetButtonName(Button b) {
 | 
	
		
			
				|  |  | +const char* getButtonName(Button b) {
 | 
	
		
			
				|  |  |      return getButton(b)->name;
 | 
	
		
			
				|  |  |  }
 |