Fix inputs and add methods
This commit is contained in:
+33
-1
@@ -180,6 +180,8 @@ struct Scene {
|
|||||||
element_pool[id]->click();
|
element_pool[id]->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#warning "This does not take rotation into account \
|
||||||
|
reference and use reverse-transform on point then AABB check instead"
|
||||||
std::vector<uint64_t> elements_at(Vec2<float> position) {
|
std::vector<uint64_t> elements_at(Vec2<float> position) {
|
||||||
std::vector<uint64_t> result;
|
std::vector<uint64_t> result;
|
||||||
|
|
||||||
@@ -211,6 +213,11 @@ struct App {
|
|||||||
uint64_t current_scene_id = 0;
|
uint64_t current_scene_id = 0;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
Vec2<float> mouse_position = {-1, -1};
|
Vec2<float> mouse_position = {-1, -1};
|
||||||
|
std::array<bool, 600> down_keys{};
|
||||||
|
std::vector<Key> pressed_keys;
|
||||||
|
std::vector<Key> released_keys;
|
||||||
|
Vec2<float> scroll = {0, 0};
|
||||||
|
std::string text = "";
|
||||||
|
|
||||||
void exit() {
|
void exit() {
|
||||||
running = false;
|
running = false;
|
||||||
@@ -246,6 +253,11 @@ struct App {
|
|||||||
|
|
||||||
Scene *scene = scene_pool[current_scene_id];
|
Scene *scene = scene_pool[current_scene_id];
|
||||||
|
|
||||||
|
pressed_keys.clear();
|
||||||
|
released_keys.clear();
|
||||||
|
scroll = {0, 0};
|
||||||
|
text = "";
|
||||||
|
|
||||||
Event e;
|
Event e;
|
||||||
while (window.poll(e)) {
|
while (window.poll(e)) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
@@ -254,6 +266,12 @@ struct App {
|
|||||||
break;
|
break;
|
||||||
case Event::MOUSE_BUTTON_DOWN:
|
case Event::MOUSE_BUTTON_DOWN:
|
||||||
scene->click(e.mouse_button.position);
|
scene->click(e.mouse_button.position);
|
||||||
|
down_keys[e.mouse_button.button] = true;
|
||||||
|
pressed_keys.push_back(e.mouse_button.button);
|
||||||
|
break;
|
||||||
|
case Event::MOUSE_BUTTON_UP:
|
||||||
|
down_keys[e.mouse_button.button] = false;
|
||||||
|
released_keys.push_back(e.mouse_button.button);
|
||||||
break;
|
break;
|
||||||
case Event::MOUSE_MOVE:
|
case Event::MOUSE_MOVE:
|
||||||
mouse_position = e.mouse_move.position;
|
mouse_position = e.mouse_move.position;
|
||||||
@@ -261,10 +279,24 @@ struct App {
|
|||||||
case Event::MOUSE_LEAVE:
|
case Event::MOUSE_LEAVE:
|
||||||
mouse_position = {-1, -1};
|
mouse_position = {-1, -1};
|
||||||
break;
|
break;
|
||||||
|
case Event::KEY_DOWN:
|
||||||
|
down_keys[e.key.key] = true;
|
||||||
|
pressed_keys.push_back(e.key.key);
|
||||||
|
break;
|
||||||
|
case Event::KEY_UP:
|
||||||
|
down_keys[e.key.key] = false;
|
||||||
|
released_keys.push_back(e.key.key);
|
||||||
|
break;
|
||||||
|
case Event::SCROLL:
|
||||||
|
scroll = e.scroll;
|
||||||
|
break;
|
||||||
|
case Event::TEXT_INPUT:
|
||||||
|
text += *e.text_input;
|
||||||
|
delete e.text_input;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
window.consume(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene->update_scene(dt);
|
scene->update_scene(dt);
|
||||||
|
|||||||
@@ -134,6 +134,16 @@ static mrb_value image_hash(mrb_state *mrb, mrb_value self) {
|
|||||||
return mrb_fixnum_value(id);
|
return mrb_fixnum_value(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value image_width(mrb_state *mrb, mrb_value self) {
|
||||||
|
uint64_t id = get_id_Image(mrb, self);
|
||||||
|
return mrb_float_value(mrb, window.get_image_size(id).x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value image_height(mrb_state *mrb, mrb_value self) {
|
||||||
|
uint64_t id = get_id_Image(mrb, self);
|
||||||
|
return mrb_float_value(mrb, window.get_image_size(id).y);
|
||||||
|
}
|
||||||
|
|
||||||
static void Animation_free(mrb_state *mrb, void *ptr) {
|
static void Animation_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
uint64_t id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
@@ -578,6 +588,18 @@ static mrb_value element_text_click_through_set(mrb_state *mrb, mrb_value self)
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value element_text_width(mrb_state *mrb, mrb_value self) {
|
||||||
|
uint64_t id = get_id_ElementText(mrb, self);
|
||||||
|
app::EText *element = (app::EText *)app::element_pool[id];
|
||||||
|
return mrb_float_value(mrb, element->size(&window).x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value element_text_height(mrb_state *mrb, mrb_value self) {
|
||||||
|
uint64_t id = get_id_ElementText(mrb, self);
|
||||||
|
app::EText *element = (app::EText *)app::element_pool[id];
|
||||||
|
return mrb_float_value(mrb, element->size(&window).y);
|
||||||
|
}
|
||||||
|
|
||||||
static void ElementRect_free(mrb_state *mrb, void *ptr) {
|
static void ElementRect_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
uint64_t id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
@@ -1413,6 +1435,58 @@ static mrb_value app_mouse_position(mrb_state *mrb, mrb_value) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value app_is_down(mrb_state *mrb, mrb_value) {
|
||||||
|
mrb_sym key_sym;
|
||||||
|
mrb_get_args(mrb, "n", &key_sym);
|
||||||
|
std::string key_name = mrb_sym2name(mrb, key_sym);
|
||||||
|
Key key = get_key(key_name);
|
||||||
|
return mrb_bool_value(app_->down_keys[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_is_pressed(mrb_state *mrb, mrb_value) {
|
||||||
|
mrb_sym key_sym;
|
||||||
|
mrb_get_args(mrb, "n", &key_sym);
|
||||||
|
std::string key_name = mrb_sym2name(mrb, key_sym);
|
||||||
|
Key key = get_key(key_name);
|
||||||
|
for (Key pressed_key : app_->pressed_keys)
|
||||||
|
if (pressed_key == key)
|
||||||
|
return mrb_bool_value(true);
|
||||||
|
return mrb_bool_value(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_is_released(mrb_state *mrb, mrb_value) {
|
||||||
|
mrb_sym key_sym;
|
||||||
|
mrb_get_args(mrb, "n", &key_sym);
|
||||||
|
std::string key_name = mrb_sym2name(mrb, key_sym);
|
||||||
|
Key key = get_key(key_name);
|
||||||
|
for (Key released_key : app_->released_keys)
|
||||||
|
if (released_key == key)
|
||||||
|
return mrb_bool_value(true);
|
||||||
|
return mrb_bool_value(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_map_key(mrb_state *mrb, mrb_value) {
|
||||||
|
mrb_sym key_sym;
|
||||||
|
mrb_sym action_sym;
|
||||||
|
mrb_get_args(mrb, "nn", &key_sym, &action_sym);
|
||||||
|
std::string key_name = mrb_sym2name(mrb, key_sym);
|
||||||
|
std::string action_name = mrb_sym2name(mrb, action_sym);
|
||||||
|
set_action_mapping(action_name, key_name);
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_scroll(mrb_state *mrb, mrb_value) {
|
||||||
|
Vec2<float> scroll = app_->scroll;
|
||||||
|
mrb_value result = mrb_hash_new(mrb);
|
||||||
|
HASH_SET(result, x, mrb_float_value(mrb, scroll.x));
|
||||||
|
HASH_SET(result, y, mrb_float_value(mrb, scroll.y));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_text_input(mrb_state *mrb, mrb_value) {
|
||||||
|
return mrb_str_new_cstr(mrb, app_->text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
static mrb_value app_exit(mrb_state *, mrb_value) {
|
static mrb_value app_exit(mrb_state *, mrb_value) {
|
||||||
app_->exit();
|
app_->exit();
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
@@ -1428,6 +1502,8 @@ inline void setup() {
|
|||||||
ADD_METHOD(Image, "==", image_equal, MRB_ARGS_REQ(1));
|
ADD_METHOD(Image, "==", image_equal, MRB_ARGS_REQ(1));
|
||||||
ADD_METHOD(Image, "eql?", image_equal, MRB_ARGS_REQ(1));
|
ADD_METHOD(Image, "eql?", image_equal, MRB_ARGS_REQ(1));
|
||||||
ADD_METHOD(Image, "hash", image_hash, MRB_ARGS_NONE());
|
ADD_METHOD(Image, "hash", image_hash, MRB_ARGS_NONE());
|
||||||
|
ADD_METHOD(Image, "width", image_width, MRB_ARGS_NONE());
|
||||||
|
ADD_METHOD(Image, "height", image_height, MRB_ARGS_NONE());
|
||||||
|
|
||||||
DEF_CLASS(Animation, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
|
DEF_CLASS(Animation, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
|
||||||
ADD_METHOD(Animation, "==", animation_equal, MRB_ARGS_REQ(1));
|
ADD_METHOD(Animation, "==", animation_equal, MRB_ARGS_REQ(1));
|
||||||
@@ -1463,6 +1539,8 @@ inline void setup() {
|
|||||||
ADD_METHOD(ElementText, "z", element_text_z_get, MRB_ARGS_NONE());
|
ADD_METHOD(ElementText, "z", element_text_z_get, MRB_ARGS_NONE());
|
||||||
ADD_METHOD(ElementText, "click_through=", element_text_click_through_set, MRB_ARGS_REQ(1));
|
ADD_METHOD(ElementText, "click_through=", element_text_click_through_set, MRB_ARGS_REQ(1));
|
||||||
ADD_METHOD(ElementText, "click_through", element_text_click_through_get, MRB_ARGS_NONE());
|
ADD_METHOD(ElementText, "click_through", element_text_click_through_get, MRB_ARGS_NONE());
|
||||||
|
ADD_METHOD(ElementText, "width", element_text_width, MRB_ARGS_NONE());
|
||||||
|
ADD_METHOD(ElementText, "height", element_text_height, MRB_ARGS_NONE());
|
||||||
|
|
||||||
DEF_CLASS(ElementRect, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1));
|
DEF_CLASS(ElementRect, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1));
|
||||||
ADD_METHOD(ElementRect, "==", element_rect_equal, MRB_ARGS_REQ(1));
|
ADD_METHOD(ElementRect, "==", element_rect_equal, MRB_ARGS_REQ(1));
|
||||||
@@ -1527,7 +1605,13 @@ inline void setup() {
|
|||||||
ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1));
|
ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1));
|
||||||
ADD_MODULE_METHOD(App, "language", app_language_get, MRB_ARGS_NONE());
|
ADD_MODULE_METHOD(App, "language", app_language_get, MRB_ARGS_NONE());
|
||||||
ADD_MODULE_METHOD(App, "mouse_position", app_mouse_position, MRB_ARGS_NONE());
|
ADD_MODULE_METHOD(App, "mouse_position", app_mouse_position, MRB_ARGS_NONE());
|
||||||
ADD_MODULE_METHOD(App, "exit", app_exit, MRB_ARGS_NONE());
|
ADD_MODULE_METHOD(App, "down?", app_is_down, MRB_ARGS_REQ(1));
|
||||||
|
ADD_MODULE_METHOD(App, "pressed?", app_is_pressed, MRB_ARGS_REQ(1));
|
||||||
|
ADD_MODULE_METHOD(App, "released?", app_is_released, MRB_ARGS_REQ(1));
|
||||||
|
ADD_MODULE_METHOD(App, "map_key", app_map_key, MRB_ARGS_REQ(2));
|
||||||
|
ADD_MODULE_METHOD(App, "scroll", app_scroll, MRB_ARGS_NONE());
|
||||||
|
ADD_MODULE_METHOD(App, "text_input", app_text_input, MRB_ARGS_NONE());
|
||||||
|
ADD_MODULE_METHOD(App, "exit!", app_exit, MRB_ARGS_NONE());
|
||||||
}
|
}
|
||||||
} // namespace definitions
|
} // namespace definitions
|
||||||
|
|
||||||
|
|||||||
+219
-22
@@ -40,6 +40,220 @@ inline Pool<Font> font_pool;
|
|||||||
// Text pool
|
// Text pool
|
||||||
inline Pool<Text> text_pool;
|
inline Pool<Text> text_pool;
|
||||||
|
|
||||||
|
enum Key : uint16_t {
|
||||||
|
Unknown = SDL_SCANCODE_UNKNOWN,
|
||||||
|
|
||||||
|
A = SDL_SCANCODE_A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
|
||||||
|
Num0 = SDL_SCANCODE_0,
|
||||||
|
Num1,
|
||||||
|
Num2,
|
||||||
|
Num3,
|
||||||
|
Num4,
|
||||||
|
Num5,
|
||||||
|
Num6,
|
||||||
|
Num7,
|
||||||
|
Num8,
|
||||||
|
Num9,
|
||||||
|
|
||||||
|
Space = SDL_SCANCODE_SPACE,
|
||||||
|
Enter = SDL_SCANCODE_RETURN,
|
||||||
|
Escape = SDL_SCANCODE_ESCAPE,
|
||||||
|
Tab = SDL_SCANCODE_TAB,
|
||||||
|
Backspace = SDL_SCANCODE_BACKSPACE,
|
||||||
|
|
||||||
|
LeftShift = SDL_SCANCODE_LSHIFT,
|
||||||
|
RightShift = SDL_SCANCODE_RSHIFT,
|
||||||
|
LeftCtrl = SDL_SCANCODE_LCTRL,
|
||||||
|
RightCtrl = SDL_SCANCODE_RCTRL,
|
||||||
|
LeftAlt = SDL_SCANCODE_LALT,
|
||||||
|
RightAlt = SDL_SCANCODE_RALT,
|
||||||
|
CapsLock = SDL_SCANCODE_CAPSLOCK,
|
||||||
|
|
||||||
|
Up = SDL_SCANCODE_UP,
|
||||||
|
Down = SDL_SCANCODE_DOWN,
|
||||||
|
Left = SDL_SCANCODE_LEFT,
|
||||||
|
Right = SDL_SCANCODE_RIGHT,
|
||||||
|
Home = SDL_SCANCODE_HOME,
|
||||||
|
End = SDL_SCANCODE_END,
|
||||||
|
PageUp = SDL_SCANCODE_PAGEUP,
|
||||||
|
PageDown = SDL_SCANCODE_PAGEDOWN,
|
||||||
|
|
||||||
|
Delete = SDL_SCANCODE_DELETE,
|
||||||
|
Insert = SDL_SCANCODE_INSERT,
|
||||||
|
|
||||||
|
Minus = SDL_SCANCODE_MINUS,
|
||||||
|
Equals = SDL_SCANCODE_EQUALS,
|
||||||
|
LeftBracket = SDL_SCANCODE_LEFTBRACKET,
|
||||||
|
RightBracket = SDL_SCANCODE_RIGHTBRACKET,
|
||||||
|
Semicolon = SDL_SCANCODE_SEMICOLON,
|
||||||
|
Apostrophe = SDL_SCANCODE_APOSTROPHE,
|
||||||
|
Grave = SDL_SCANCODE_GRAVE,
|
||||||
|
Comma = SDL_SCANCODE_COMMA,
|
||||||
|
Period = SDL_SCANCODE_PERIOD,
|
||||||
|
Slash = SDL_SCANCODE_SLASH,
|
||||||
|
Backslash = SDL_SCANCODE_NONUSBACKSLASH,
|
||||||
|
|
||||||
|
F1 = SDL_SCANCODE_F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
|
||||||
|
MouseLeft = 513,
|
||||||
|
MouseMiddle,
|
||||||
|
MouseRight
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::pair<std::string, Key> KEY_NAMES[] = {
|
||||||
|
{"a", Key::A},
|
||||||
|
{"b", Key::B},
|
||||||
|
{"c", Key::C},
|
||||||
|
{"d", Key::D},
|
||||||
|
{"e", Key::E},
|
||||||
|
{"f", Key::F},
|
||||||
|
{"g", Key::G},
|
||||||
|
{"h", Key::H},
|
||||||
|
{"i", Key::I},
|
||||||
|
{"j", Key::J},
|
||||||
|
{"k", Key::K},
|
||||||
|
{"l", Key::L},
|
||||||
|
{"m", Key::M},
|
||||||
|
{"n", Key::N},
|
||||||
|
{"o", Key::O},
|
||||||
|
{"p", Key::P},
|
||||||
|
{"q", Key::Q},
|
||||||
|
{"r", Key::R},
|
||||||
|
{"s", Key::S},
|
||||||
|
{"t", Key::T},
|
||||||
|
{"u", Key::U},
|
||||||
|
{"v", Key::V},
|
||||||
|
{"w", Key::W},
|
||||||
|
{"x", Key::X},
|
||||||
|
{"y", Key::Y},
|
||||||
|
{"z", Key::Z},
|
||||||
|
|
||||||
|
{"num0", Key::Num0},
|
||||||
|
{"num1", Key::Num1},
|
||||||
|
{"num2", Key::Num2},
|
||||||
|
{"num3", Key::Num3},
|
||||||
|
{"num4", Key::Num4},
|
||||||
|
{"num5", Key::Num5},
|
||||||
|
{"num6", Key::Num6},
|
||||||
|
{"num7", Key::Num7},
|
||||||
|
{"num8", Key::Num8},
|
||||||
|
{"num9", Key::Num9},
|
||||||
|
|
||||||
|
{"space", Key::Space},
|
||||||
|
{"enter", Key::Enter},
|
||||||
|
{"escape", Key::Escape},
|
||||||
|
{"tab", Key::Tab},
|
||||||
|
{"backspace", Key::Backspace},
|
||||||
|
|
||||||
|
{"left_shift", Key::LeftShift},
|
||||||
|
{"right_shift", Key::RightShift},
|
||||||
|
{"left_ctrl", Key::LeftCtrl},
|
||||||
|
{"right_ctrl", Key::RightCtrl},
|
||||||
|
{"left_alt", Key::LeftAlt},
|
||||||
|
{"right_alt", Key::RightAlt},
|
||||||
|
{"capslock", Key::CapsLock},
|
||||||
|
|
||||||
|
{"up", Key::Up},
|
||||||
|
{"down", Key::Down},
|
||||||
|
{"left", Key::Left},
|
||||||
|
{"right", Key::Right},
|
||||||
|
{"home", Key::Home},
|
||||||
|
{"end", Key::End},
|
||||||
|
{"page_up", Key::PageUp},
|
||||||
|
{"page_down", Key::PageDown},
|
||||||
|
|
||||||
|
{"delete", Key::Delete},
|
||||||
|
{"insert", Key::Insert},
|
||||||
|
|
||||||
|
{"minus", Key::Minus},
|
||||||
|
{"equals", Key::Equals},
|
||||||
|
{"left_bracket", Key::LeftBracket},
|
||||||
|
{"right_bracket", Key::RightBracket},
|
||||||
|
{"semicolon", Key::Semicolon},
|
||||||
|
{"apostrophe", Key::Apostrophe},
|
||||||
|
{"grave", Key::Grave},
|
||||||
|
{"comma", Key::Comma},
|
||||||
|
{"period", Key::Period},
|
||||||
|
{"slash", Key::Slash},
|
||||||
|
{"backslash", Key::Backslash},
|
||||||
|
|
||||||
|
{"f1", Key::F1},
|
||||||
|
{"f2", Key::F2},
|
||||||
|
{"f3", Key::F3},
|
||||||
|
{"f4", Key::F4},
|
||||||
|
{"f5", Key::F5},
|
||||||
|
{"f6", Key::F6},
|
||||||
|
{"f7", Key::F7},
|
||||||
|
{"f8", Key::F8},
|
||||||
|
{"f9", Key::F9},
|
||||||
|
{"f10", Key::F10},
|
||||||
|
{"f11", Key::F11},
|
||||||
|
{"f12", Key::F12},
|
||||||
|
|
||||||
|
{"mouse_left", Key::MouseLeft},
|
||||||
|
{"mouse_middle", Key::MouseMiddle},
|
||||||
|
{"mouse_right", Key::MouseRight}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Key get_key_from_name(std::string_view name) {
|
||||||
|
for (const auto &[key_name, key] : KEY_NAMES)
|
||||||
|
if (key_name == name)
|
||||||
|
return key;
|
||||||
|
return Key::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unordered_map<std::string, Key> action_key_map;
|
||||||
|
|
||||||
|
inline void set_action_mapping(const std::string &action_name, const std::string &key_name) {
|
||||||
|
Key key = get_key_from_name(key_name);
|
||||||
|
if (key != Key::Unknown)
|
||||||
|
action_key_map[action_name] = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Key get_key(std::string &name) {
|
||||||
|
auto it = action_key_map.find(name);
|
||||||
|
if (it != action_key_map.end())
|
||||||
|
return it->second;
|
||||||
|
return get_key_from_name(name);
|
||||||
|
}
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
enum Type {
|
enum Type {
|
||||||
NONE,
|
NONE,
|
||||||
@@ -56,20 +270,15 @@ struct Event {
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t key;
|
Key key;
|
||||||
} key;
|
} key;
|
||||||
|
|
||||||
struct {
|
std::string *text_input;
|
||||||
char *text;
|
|
||||||
uint32_t length;
|
Vec2<float> scroll;
|
||||||
} text_input;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
float x, y;
|
Key button;
|
||||||
} scroll;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint8_t button;
|
|
||||||
Vec2<float> position;
|
Vec2<float> position;
|
||||||
} mouse_button;
|
} mouse_button;
|
||||||
|
|
||||||
@@ -125,16 +334,6 @@ public:
|
|||||||
|
|
||||||
bool poll(Event &event); // returns true if an event was polled, false otherwise
|
bool poll(Event &event); // returns true if an event was polled, false otherwise
|
||||||
|
|
||||||
// consumes an event, (mostly for text input, to free the text input buffer)
|
|
||||||
// but also so the user can decide when they're done with the event explicitly.
|
|
||||||
void consume(Event &event);
|
|
||||||
|
|
||||||
// Text input
|
|
||||||
// Starts accepting Unicode text input events, and stops acceptong normal key down/up events for those keys.
|
|
||||||
|
|
||||||
void start_text_input();
|
|
||||||
void stop_text_input();
|
|
||||||
|
|
||||||
// Clipboard get
|
// Clipboard get
|
||||||
|
|
||||||
// To be free'd by the caller after use.
|
// To be free'd by the caller after use.
|
||||||
@@ -190,8 +389,6 @@ private:
|
|||||||
|
|
||||||
std::vector<struct RenderInstruction> render_instructions;
|
std::vector<struct RenderInstruction> render_instructions;
|
||||||
|
|
||||||
bool text_input_active;
|
|
||||||
|
|
||||||
void compute_transform();
|
void compute_transform();
|
||||||
|
|
||||||
bool mouse_in_window(const Vec2<float> real_position, Vec2<float> &virtual_position);
|
bool mouse_in_window(const Vec2<float> real_position, Vec2<float> &virtual_position);
|
||||||
|
|||||||
+12
-38
@@ -12,7 +12,7 @@ bg_animation = Animation.new [bg_image1, bg_image2], fps: 5
|
|||||||
App.language = :en
|
App.language = :en
|
||||||
App.localize(:en, :btn_text, "Click %{name}!")
|
App.localize(:en, :btn_text, "Click %{name}!")
|
||||||
|
|
||||||
text = ElementText.new :btn_text, default_font, 0xFFFFFF, {name: "Me"}, position: {x: 50, y: 50}, z: 1, click_through: true, alpha: 1
|
text = ElementText.new :btn_text, default_font, 0xFFFF00, {name: "Me"}, position: {x: 50, y: 50}, z: 1, click_through: true, alpha: 1
|
||||||
|
|
||||||
rect = ElementRect.new 100, 25, 0xFF0000, position: {x: 50, y: 50}, z: 0, rotation: 60, scale: { x: 1.5, y: 1 }, alpha: 0.4
|
rect = ElementRect.new 100, 25, 0xFF0000, position: {x: 50, y: 50}, z: 0, rotation: 60, scale: { x: 1.5, y: 1 }, alpha: 0.4
|
||||||
|
|
||||||
@@ -28,40 +28,7 @@ rect.on_click do
|
|||||||
text.params!
|
text.params!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
App.map_key :mouse_left, :press
|
||||||
=begin
|
|
||||||
|
|
||||||
input handling:
|
|
||||||
|
|
||||||
App.map_key(:space, :jump) # maps the space key to a :jump action (multiple keys can be mapped to the same action)
|
|
||||||
# all events here are in english ones, (so need to find which english key corresponds to the key in the current language of the keyboard)
|
|
||||||
key can be one of [:a..:z, :0..:9, :space, :enter, :shift, :ctrl, :alt, :tab, :backspace, :escape, :up, :down, :left, :right, :middle]
|
|
||||||
|
|
||||||
this can be checked anywhere using:
|
|
||||||
|
|
||||||
App.down?(:jump) # returns true if the jump action is currently being pressed
|
|
||||||
App.pressed?(:jump) # returns true if the jump action was just pressed this frame
|
|
||||||
App.released?(:jump) # returns true if the jump action was just released this frame
|
|
||||||
|
|
||||||
for wheel, you can use:
|
|
||||||
|
|
||||||
App.wheel # returns a hash with :x and :y values representing the wheel movement since the last frame (can be used for zooming, scrolling, etc.)
|
|
||||||
|
|
||||||
mouse position can be accessed with:
|
|
||||||
|
|
||||||
App.mouse_position # returns a hash with :x and :y values representing the current mouse position in the window
|
|
||||||
|
|
||||||
For localized input, you can use:
|
|
||||||
|
|
||||||
App.start_text_input!
|
|
||||||
|
|
||||||
App.text_input # returns the text typed this frame as a string (useful for text input fields, chat, etc.)
|
|
||||||
# can be multiple characters if the user types fast, so you should append it to a string variable to get the full input
|
|
||||||
|
|
||||||
App.stop_text_input!
|
|
||||||
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
main_scene.on_update do |delta_time|
|
main_scene.on_update do |delta_time|
|
||||||
# puts "Delta time: #{delta_time}ms"
|
# puts "Delta time: #{delta_time}ms"
|
||||||
@@ -69,13 +36,20 @@ main_scene.on_update do |delta_time|
|
|||||||
# runs at 60fps, so you should see around 16-17ms being printed
|
# runs at 60fps, so you should see around 16-17ms being printed
|
||||||
|
|
||||||
el = main_scene.elements_at(App.mouse_position)
|
el = main_scene.elements_at(App.mouse_position)
|
||||||
|
|
||||||
|
puts App.text_input if App.text_input != ""
|
||||||
|
|
||||||
|
next unless App.pressed?(:press)
|
||||||
|
|
||||||
|
puts "#{App.pressed?(:press)}, #{App.down?(:press)}, #{App.released?(:press)}"
|
||||||
|
|
||||||
for elem in el
|
for elem in el
|
||||||
if elem == image_element
|
if elem == image_element
|
||||||
#puts "Hovering over image element"
|
puts "Down over image element"
|
||||||
elsif elem == rect
|
elsif elem == rect
|
||||||
#puts "Hovering over rect element"
|
puts "Down over rect element"
|
||||||
elsif elem == text
|
elsif elem == text
|
||||||
#puts "Hovering over text element"
|
puts "Down over text element"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+6
-31
@@ -15,7 +15,7 @@ Window::Window(Vec2<float> size, const char *title) {
|
|||||||
|
|
||||||
compute_transform();
|
compute_transform();
|
||||||
|
|
||||||
text_input_active = false;
|
SDL_StartTextInput(window);
|
||||||
|
|
||||||
white_tex = SDL_CreateTexture(
|
white_tex = SDL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
@@ -370,22 +370,17 @@ bool Window::poll(Event &event) {
|
|||||||
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
event.type = Event::KEY_DOWN;
|
event.type = Event::KEY_DOWN;
|
||||||
event.key.key = sdl_event.key.scancode;
|
event.key.key = (Key)sdl_event.key.scancode;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_KEY_UP:
|
case SDL_EVENT_KEY_UP:
|
||||||
event.type = Event::KEY_UP;
|
event.type = Event::KEY_UP;
|
||||||
event.key.key = sdl_event.key.scancode;
|
event.key.key = (Key)sdl_event.key.scancode;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_TEXT_INPUT:
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
if (!text_input_active)
|
|
||||||
return false;
|
|
||||||
event.type = Event::TEXT_INPUT;
|
event.type = Event::TEXT_INPUT;
|
||||||
event.text_input.length = strlen(sdl_event.text.text);
|
event.text_input = new std::string(sdl_event.text.text);
|
||||||
event.text_input.text = (char *)malloc(event.text_input.length + 1);
|
|
||||||
strcpy(event.text_input.text, sdl_event.text.text);
|
|
||||||
event.text_input.text[event.text_input.length] = '\0';
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||||
@@ -394,7 +389,7 @@ bool Window::poll(Event &event) {
|
|||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||||
event.type = Event::MOUSE_BUTTON_DOWN;
|
event.type = Event::MOUSE_BUTTON_DOWN;
|
||||||
event.mouse_button.button = sdl_event.button.button;
|
event.mouse_button.button = (Key)(sdl_event.button.button + 512);
|
||||||
Vec2<float> virtual_position;
|
Vec2<float> virtual_position;
|
||||||
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
||||||
event.mouse_button.position = virtual_position;
|
event.mouse_button.position = virtual_position;
|
||||||
@@ -404,7 +399,7 @@ bool Window::poll(Event &event) {
|
|||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
event.type = Event::MOUSE_BUTTON_UP;
|
event.type = Event::MOUSE_BUTTON_UP;
|
||||||
event.mouse_button.button = sdl_event.button.button;
|
event.mouse_button.button = (Key)(sdl_event.button.button + 512);
|
||||||
Vec2<float> virtual_position;
|
Vec2<float> virtual_position;
|
||||||
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
||||||
event.mouse_button.position = virtual_position;
|
event.mouse_button.position = virtual_position;
|
||||||
@@ -444,26 +439,6 @@ bool Window::poll(Event &event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::consume(Event &event) {
|
|
||||||
if (event.type == Event::TEXT_INPUT) {
|
|
||||||
free(event.text_input.text);
|
|
||||||
event.text_input.text = nullptr;
|
|
||||||
event.text_input.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.type = Event::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::start_text_input() {
|
|
||||||
text_input_active = true;
|
|
||||||
SDL_StartTextInput(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::stop_text_input() {
|
|
||||||
text_input_active = false;
|
|
||||||
SDL_StopTextInput(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Window::paste() {
|
const char *Window::paste() {
|
||||||
const char *clipboard_text = SDL_GetClipboardText();
|
const char *clipboard_text = SDL_GetClipboardText();
|
||||||
if (clipboard_text == nullptr) {
|
if (clipboard_text == nullptr) {
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,90 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
int N = 1000000; // 1,000,000 tries
|
||||||
|
int L = 20; // string length
|
||||||
|
|
||||||
|
string random_string(size_t length) {
|
||||||
|
static const string chars =
|
||||||
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
|
||||||
|
static random_device rd;
|
||||||
|
static mt19937 gen(rd());
|
||||||
|
|
||||||
|
uniform_int_distribution<> dist(0, chars.size() - 1);
|
||||||
|
|
||||||
|
string s;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
s += chars[dist(gen)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_array(int length) {
|
||||||
|
std::unordered_map<std::string, int> hash_map;
|
||||||
|
hash_map.reserve(length * 2); // Reserve more to avoid rehashing
|
||||||
|
std::vector<std::pair<std::string, int>> array;
|
||||||
|
array.reserve(length);
|
||||||
|
|
||||||
|
vector<string> keys;
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
string key = random_string(L);
|
||||||
|
|
||||||
|
keys.push_back(key);
|
||||||
|
|
||||||
|
hash_map[key] = i;
|
||||||
|
array.emplace_back(key, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
string &key = keys[i % length];
|
||||||
|
|
||||||
|
auto it = hash_map.find(key);
|
||||||
|
|
||||||
|
volatile int value = it->second;
|
||||||
|
(void)value;
|
||||||
|
}
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
auto hash_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||||
|
|
||||||
|
start = std::chrono::high_resolution_clock::now();
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
string &key = keys[i % length];
|
||||||
|
|
||||||
|
auto it = std::find_if(array.begin(), array.end(), [&key](const auto &pair) {
|
||||||
|
return pair.first == key;
|
||||||
|
});
|
||||||
|
|
||||||
|
volatile int value = it->second;
|
||||||
|
(void)value;
|
||||||
|
}
|
||||||
|
end = std::chrono::high_resolution_clock::now();
|
||||||
|
auto array_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||||
|
|
||||||
|
std::cout << length << "," << hash_duration << "," << array_duration << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "elements,hash,array\n";
|
||||||
|
|
||||||
|
for (int length = 1; length <= 10; length++)
|
||||||
|
test_array(length);
|
||||||
|
for (int length = 10; length <= 100; length += 10)
|
||||||
|
test_array(length);
|
||||||
|
for (int length = 100; length <= 1000; length += 100)
|
||||||
|
test_array(length);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
elements,hash,array
|
||||||
|
1,53,36
|
||||||
|
2,57,49
|
||||||
|
3,83,65
|
||||||
|
4,99,84
|
||||||
|
5,117,99
|
||||||
|
6,132,115
|
||||||
|
7,145,128
|
||||||
|
8,163,141
|
||||||
|
9,174,156
|
||||||
|
10,191,167
|
||||||
|
10,190,169
|
||||||
|
20,339,306
|
||||||
|
30,74,442
|
||||||
|
40,71,579
|
||||||
|
50,78,719
|
||||||
|
60,74,874
|
||||||
|
70,75,1064
|
||||||
|
80,83,1244
|
||||||
|
90,83,1394
|
||||||
|
100,85,1477
|
||||||
|
100,86,1485
|
||||||
|
200,80,2912
|
||||||
|
300,82,4401
|
||||||
|
400,82,5946
|
||||||
|
500,83,7526
|
||||||
|
600,84,9256
|
||||||
|
700,86,10927
|
||||||
|
800,88,12828
|
||||||
|
900,89,14502
|
||||||
|
1000,90,16302
|
||||||
|
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
df = pd.read_csv("benchmark.csv")
|
||||||
|
|
||||||
|
plt.figure(figsize=(10, 6))
|
||||||
|
|
||||||
|
plt.plot(df["elements"], df["hash"], marker='o', label="Hash map")
|
||||||
|
plt.plot(df["elements"], df["array"], marker='o', label="Array")
|
||||||
|
|
||||||
|
# LOG SCALE
|
||||||
|
plt.xscale("log")
|
||||||
|
plt.yscale("log")
|
||||||
|
|
||||||
|
plt.xlabel("Number of elements (log scale)")
|
||||||
|
plt.ylabel("Time (ms) (log scale)")
|
||||||
|
plt.title("Array vs Hash Map Lookup Performance")
|
||||||
|
|
||||||
|
plt.grid(True, which="both", linestyle="--", alpha=0.5)
|
||||||
|
plt.legend()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
plt.savefig("benchmark.png", dpi=200, bbox_inches="tight")
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 145 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
Reference in New Issue
Block a user