Finish basic ui binding to ruby
This commit is contained in:
+43
-5
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace app {
|
||||
struct Element {
|
||||
int reference_count = 0;
|
||||
Vec2<float> position = {0, 0};
|
||||
float rotation = 0;
|
||||
Vec2<float> scale = {1, 1};
|
||||
@@ -51,11 +52,10 @@ struct EImage : Element {
|
||||
struct EText : Element {
|
||||
Localization::Key key;
|
||||
int font_id;
|
||||
int font_size = 16;
|
||||
Color color = {255, 255, 255, 255};
|
||||
|
||||
EText(Localization::Key key, int font_id, int font_size, Color color)
|
||||
: key(key), font_id(font_id), font_size(font_size), color(color) {}
|
||||
EText(Localization::Key key, int font_id, Color color)
|
||||
: key(key), font_id(font_id), color(color) {}
|
||||
|
||||
Vec2<float> size(Window *window) override {
|
||||
return window->get_text_size(text_id);
|
||||
@@ -96,9 +96,20 @@ struct ERect : Element {
|
||||
inline Pool<Element *> element_pool;
|
||||
|
||||
struct Scene {
|
||||
bool unused = false;
|
||||
std::vector<int> element_ids;
|
||||
Ruby::Block update;
|
||||
|
||||
~Scene() {
|
||||
for (const int &id : element_ids) {
|
||||
element_pool[id]->reference_count--;
|
||||
if (element_pool[id]->reference_count <= 0) {
|
||||
delete element_pool[id];
|
||||
element_pool.release(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_element(int element_id) {
|
||||
auto it = std::lower_bound(
|
||||
element_ids.begin(),
|
||||
@@ -108,9 +119,22 @@ struct Scene {
|
||||
return element_pool[a]->z < element_pool[b]->z || (element_pool[a]->z == element_pool[b]->z && a < b);
|
||||
}
|
||||
);
|
||||
element_pool[element_id]->reference_count++;
|
||||
element_ids.insert(it, element_id);
|
||||
}
|
||||
|
||||
void delete_element(int element_id) {
|
||||
auto it = std::find(element_ids.begin(), element_ids.end(), element_id);
|
||||
if (it != element_ids.end()) {
|
||||
element_pool[element_id]->reference_count--;
|
||||
if (element_pool[element_id]->reference_count <= 0) {
|
||||
delete element_pool[element_id];
|
||||
element_pool.release(element_id);
|
||||
}
|
||||
element_ids.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void update_scene(uint64_t delta_time) {
|
||||
if (!mrb_nil_p(update.proc)) {
|
||||
int x = mrb_gc_arena_save(Ruby::mrb);
|
||||
@@ -147,6 +171,21 @@ struct App {
|
||||
int current_scene_id = 0;
|
||||
bool running = true;
|
||||
|
||||
void switch_to_scene(int scene_id) {
|
||||
int scene_pool_size = (int)scene_pool.all().size();
|
||||
for (int i = 0; i < scene_pool_size; ++i) {
|
||||
auto &val = scene_pool[i];
|
||||
if (i == scene_id && val != nullptr && val->unused)
|
||||
val->unused = false;
|
||||
if (val != nullptr && val->unused) {
|
||||
delete val;
|
||||
scene_pool.release(i);
|
||||
}
|
||||
}
|
||||
|
||||
current_scene_id = scene_id;
|
||||
}
|
||||
|
||||
App(Vec2<float> size, const char *title, Animation loading_animation) {
|
||||
window.update(size, title);
|
||||
#warning "Should try to center the loading image or scale it to fit the screen"
|
||||
@@ -154,7 +193,7 @@ struct App {
|
||||
EImage *image = new EImage(loading_animation);
|
||||
int image_id = element_pool.acquire(image);
|
||||
loading_scene->add_element(image_id);
|
||||
scene_pool.acquire(loading_scene);
|
||||
current_scene_id = scene_pool.acquire(loading_scene);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -183,7 +222,6 @@ struct App {
|
||||
break;
|
||||
case Event::MOUSE_BUTTON_DOWN:
|
||||
scene->click(&window, e.mouse_button.position);
|
||||
printf("DT: %lu ms\n", dt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -12,10 +12,20 @@ struct Block {
|
||||
|
||||
Block() : proc(mrb_nil_value()) {}
|
||||
|
||||
void set_proc(mrb_value new_proc) {
|
||||
if (!mrb_nil_p(proc))
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
proc = new_proc;
|
||||
if (!mrb_nil_p(proc))
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
|
||||
Block(const Block &) = delete;
|
||||
Block &operator=(const Block &) = delete;
|
||||
|
||||
mrb_value call(int argc = 0, mrb_value *argv = nullptr) const {
|
||||
if (mrb_nil_p(proc))
|
||||
return mrb_nil_value();
|
||||
return mrb_funcall(mrb, proc, "call", argc, argv);
|
||||
}
|
||||
|
||||
@@ -23,4 +33,10 @@ struct Block {
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
}
|
||||
};
|
||||
|
||||
inline void run_string(const char *code, size_t length) {
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
mrb_load_nstring(mrb, code, length);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
}
|
||||
}; // namespace Ruby
|
||||
@@ -5,11 +5,11 @@ namespace Localization {
|
||||
using Key = uint16_t;
|
||||
|
||||
// Maps localization keys to their string identifiers. This is used for text elements to look up the correct localized string.
|
||||
extern std::unordered_map<std::string, Key> localization_key_map;
|
||||
inline std::unordered_map<std::string, Key> localization_key_map;
|
||||
|
||||
using LanguageCode = uint32_t; // 32-bit integer to store the language code (e.g., "en", "fr", "es")
|
||||
|
||||
extern LanguageCode current_language; // The currently active language code
|
||||
inline LanguageCode current_language = 'e' << 24 | 'n' << 16;
|
||||
|
||||
using JoinedKey = uint64_t; // 64-bit integer to store the joined language code and key
|
||||
|
||||
@@ -17,12 +17,47 @@ inline JoinedKey join_keys(LanguageCode lang_code, Key loc_key) {
|
||||
return (static_cast<JoinedKey>(lang_code) << 16) | loc_key;
|
||||
}
|
||||
|
||||
extern std::unordered_map<JoinedKey, std::string> localized_strings;
|
||||
inline std::unordered_map<JoinedKey, std::string> localized_strings;
|
||||
|
||||
inline std::string get(Key key) {
|
||||
auto it = localized_strings.find(join_keys(current_language, key));
|
||||
if (it != localized_strings.end())
|
||||
return it->second;
|
||||
return "";
|
||||
|
||||
for (const auto &[joined, value] : localized_strings) {
|
||||
Key k = (Key)(joined & 0xFFFF);
|
||||
if (k == key)
|
||||
return value;
|
||||
}
|
||||
|
||||
return "Localization not set!";
|
||||
}
|
||||
|
||||
inline LanguageCode lang_from_sym(mrb_state *mrb, mrb_sym sym) {
|
||||
const char *s = mrb_sym2name(mrb, sym);
|
||||
size_t len = strlen(s);
|
||||
|
||||
if (len == 0 || len > 4)
|
||||
return 0;
|
||||
|
||||
LanguageCode code = 0;
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
code |= (static_cast<LanguageCode>(s[i]) << (8 * (3 - i)));
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
inline Key key_from_sym(mrb_state *mrb, mrb_sym sym) {
|
||||
const char *key_name = mrb_sym2name(mrb, sym);
|
||||
|
||||
auto it = localization_key_map.find(key_name);
|
||||
if (it != localization_key_map.end())
|
||||
return it->second;
|
||||
|
||||
Key new_id = (Key)localization_key_map.size();
|
||||
localization_key_map[key_name] = new_id;
|
||||
return new_id;
|
||||
}
|
||||
} // namespace Localization
|
||||
@@ -4,9 +4,12 @@
|
||||
#include "mruby.h"
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/compile.h"
|
||||
#include "mruby/data.h"
|
||||
#include "mruby/hash.h"
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/value.h"
|
||||
#include "mruby/variable.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
struct Color {
|
||||
uint8_t r, g, b, a;
|
||||
uint8_t r, g, b = 0, a = 255;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user