12
flake.lock
generated
12
flake.lock
generated
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1752950548,
|
||||
"narHash": "sha256-NS6BLD0lxOrnCiEOcvQCDVPXafX1/ek1dfJHX1nUIzc=",
|
||||
"lastModified": 1754725699,
|
||||
"narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c87b95e25065c028d31a94f06a62927d18763fdf",
|
||||
"rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -76,11 +76,11 @@
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1752101817,
|
||||
"narHash": "sha256-NUSPmdoPUYQDxFHnSJX9yV+tluZVmR62P4IjPTnm8dY=",
|
||||
"lastModified": 1754816070,
|
||||
"narHash": "sha256-Yyup5t4BQslBIip8rLb8kEbNs8iAB15Oaad9Y08P09U=",
|
||||
"owner": "slendidev",
|
||||
"repo": "wlroots-lunar",
|
||||
"rev": "ef7aadec563747f8e1026b2c339d1132ae63f8a0",
|
||||
"rev": "2fd8463ad8c78469744d854b3d155a3b55fc7ae1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -11,9 +11,10 @@ return {
|
||||
keybindings = {
|
||||
{ bind = main("Shift-Q"), action = lunar.quit_compositor },
|
||||
{ bind = main("Shift-R"), action = lunar.reload_config },
|
||||
{ bind = main("R"), action = lunar.recenter },
|
||||
{ bind = main("Tab"), action = lunar.cycle_next },
|
||||
},
|
||||
space = {
|
||||
offset = { 0, 0, 0 },
|
||||
radius = 0.7,
|
||||
xwayland = {
|
||||
lazy = false,
|
||||
},
|
||||
}
|
||||
|
||||
54
src/Config.c
54
src/Config.c
@@ -1,5 +1,7 @@
|
||||
#include "Config.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "lua_helpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -155,6 +157,16 @@ int config_load_ref(lua_State *L, int idx, Config *out)
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
// ======== DEFAULTS ========
|
||||
out->space.offset = (Vector3) { 0, 0, 0 };
|
||||
out->space.initial_center = (Vector3) { 0, 1, 0 };
|
||||
out->space.radius = 0.7f;
|
||||
out->space.window_scale = 0.001f;
|
||||
// ====== END DEFAULTS ======
|
||||
|
||||
out->xwayland.enabled = true;
|
||||
out->xwayland.lazy = true;
|
||||
|
||||
int cfg_abs = lua_absindex(L, idx);
|
||||
if (push_config_table_from_idx(L, cfg_abs) != 0)
|
||||
return -1;
|
||||
@@ -215,12 +227,12 @@ int config_load_ref(lua_State *L, int idx, Config *out)
|
||||
if (ok == 0) {
|
||||
free(arr);
|
||||
} else if (ok < n) {
|
||||
BindingRef *shr = (BindingRef *)realloc(arr, ok * sizeof(*arr));
|
||||
BindingRef *shr = (BindingRef *)realloc(arr, ok * sizeof(*shr));
|
||||
if (shr)
|
||||
arr = shr;
|
||||
}
|
||||
|
||||
out->keybindings.items = (ok ? arr : NULL);
|
||||
out->keybindings.items = ok ? arr : NULL;
|
||||
out->keybindings.count = ok;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
@@ -240,6 +252,44 @@ int config_load_ref(lua_State *L, int idx, Config *out)
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "space");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_getfield(L, -1, "offset");
|
||||
if (lua_istable(L, -1) || lua_isuserdata(L, -1))
|
||||
out->space.offset = lua_readVector3(L, lua_absindex(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "initial_center");
|
||||
if (lua_istable(L, -1) || lua_isuserdata(L, -1))
|
||||
out->space.initial_center = lua_readVector3(L, lua_absindex(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "radius");
|
||||
if (lua_isnumber(L, -1))
|
||||
out->space.radius = (float)lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "window_scale");
|
||||
if (lua_isnumber(L, -1))
|
||||
out->space.window_scale = (float)lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "xwayland");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_getfield(L, -1, "enabled");
|
||||
if (lua_isboolean(L, -1))
|
||||
out->xwayland.enabled = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "lazy");
|
||||
if (lua_isboolean(L, -1))
|
||||
out->xwayland.lazy = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
16
src/Config.h
16
src/Config.h
@@ -1,9 +1,11 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <raylib.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
typedef struct {
|
||||
@@ -23,6 +25,18 @@ typedef struct {
|
||||
BindingRef *items;
|
||||
size_t count;
|
||||
} keybindings;
|
||||
|
||||
struct {
|
||||
Vector3 offset;
|
||||
Vector3 initial_center;
|
||||
float radius;
|
||||
float window_scale;
|
||||
} space;
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
bool lazy;
|
||||
} xwayland;
|
||||
} Config;
|
||||
|
||||
char const *get_config_path(void);
|
||||
|
||||
203
src/LunarWM.c
203
src/LunarWM.c
@@ -1,5 +1,7 @@
|
||||
#include "LunarWM.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -66,6 +68,7 @@ void toplevel_destroy_notify(struct wl_listener *l, void *)
|
||||
bool LunarWM_Toplevel_init(
|
||||
LunarWM_Toplevel *tl, struct LunarWM *wm, struct wlr_xdg_toplevel *xdg)
|
||||
{
|
||||
tl->id = vector_size(wm->wayland.v_toplevels) + 1;
|
||||
tl->server = wm;
|
||||
tl->xdg_toplevel = xdg;
|
||||
tl->surface = xdg->base->surface;
|
||||
@@ -128,6 +131,33 @@ bool LunarWM_Toplevel_update(LunarWM_Toplevel *this)
|
||||
return true;
|
||||
}
|
||||
|
||||
void LunarWM_Toplevel_focus(LunarWM_Toplevel *this)
|
||||
{
|
||||
if (!this)
|
||||
return;
|
||||
|
||||
LunarWM *wm = this->server;
|
||||
struct wlr_seat *seat = wm->wayland.seat;
|
||||
struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
|
||||
struct wlr_surface *surface = this->xdg_toplevel->base->surface;
|
||||
if (prev_surface == surface) {
|
||||
return;
|
||||
}
|
||||
if (prev_surface) {
|
||||
struct wlr_xdg_toplevel *prev_toplevel
|
||||
= wlr_xdg_toplevel_try_from_wlr_surface(prev_surface);
|
||||
if (prev_toplevel != NULL) {
|
||||
wlr_xdg_toplevel_set_activated(prev_toplevel, false);
|
||||
}
|
||||
}
|
||||
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
|
||||
wlr_xdg_toplevel_set_activated(this->xdg_toplevel, true);
|
||||
if (keyboard != NULL) {
|
||||
wlr_seat_keyboard_notify_enter(seat, surface, keyboard->keycodes,
|
||||
keyboard->num_keycodes, &keyboard->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
static void keysym_name(xkb_keysym_t sym, char *buf, size_t bufsz)
|
||||
{
|
||||
if (bufsz == 0)
|
||||
@@ -420,6 +450,13 @@ static bool init_wayland(LunarWM *this)
|
||||
wl_signal_add(&this->wayland.xdg_shell->events.new_popup,
|
||||
&this->wayland.new_xdg_popup_listener);
|
||||
|
||||
if (this->cman->cfg.xwayland.enabled) {
|
||||
this->wayland.xwayland = wlr_xwayland_create(this->wayland.display,
|
||||
this->wayland.compositor, this->cman->cfg.xwayland.lazy);
|
||||
|
||||
setenv("DISPLAY", this->wayland.xwayland->display_name, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1052,6 +1089,34 @@ static bool init_xr(LunarWM *this)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sync_config(LunarWM *this) { }
|
||||
|
||||
static int l_cycle_next(lua_State *L)
|
||||
{
|
||||
if (vector_size(g_wm.wayland.v_toplevels) == 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_wm.wayland.current_focus++;
|
||||
if (g_wm.wayland.current_focus >= vector_size(g_wm.wayland.v_toplevels)) {
|
||||
g_wm.wayland.current_focus = 0;
|
||||
}
|
||||
|
||||
LunarWM_Toplevel *tl = g_wm.wayland.v_toplevels[g_wm.wayland.current_focus];
|
||||
LunarWM_Toplevel_focus(tl);
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_recenter(lua_State *L)
|
||||
{
|
||||
g_wm.renderer.center = g_wm.renderer.camera.position;
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_reload_config(lua_State *L)
|
||||
{
|
||||
ConfigManager *cm = g_wm.cman;
|
||||
@@ -1061,6 +1126,7 @@ static int l_reload_config(lua_State *L)
|
||||
}
|
||||
|
||||
config_manager_reload(cm);
|
||||
sync_config(&g_wm);
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
@@ -1068,7 +1134,8 @@ static int l_reload_config(lua_State *L)
|
||||
static int l_quit_compositor(lua_State *L)
|
||||
{
|
||||
LunarWM_terminate(&g_wm);
|
||||
return 0;
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool LunarWM_init(LunarWM *this)
|
||||
@@ -1086,6 +1153,7 @@ bool LunarWM_init(LunarWM *this)
|
||||
this->renderer.camera.up = (Vector3) { 0, 1, 0 };
|
||||
this->renderer.camera.fovy = 45;
|
||||
this->renderer.camera.projection = CAMERA_PERSPECTIVE;
|
||||
this->renderer.center = (Vector3) { 0, 0, 0 };
|
||||
}
|
||||
|
||||
this->cman = config_manager_create(get_config_path());
|
||||
@@ -1099,9 +1167,16 @@ bool LunarWM_init(LunarWM *this)
|
||||
lua_setfield(L, -2, "quit_compositor");
|
||||
lua_pushcfunction(L, l_reload_config);
|
||||
lua_setfield(L, -2, "reload_config");
|
||||
lua_pushcfunction(L, l_recenter);
|
||||
lua_setfield(L, -2, "recenter");
|
||||
lua_pushcfunction(L, l_cycle_next);
|
||||
lua_setfield(L, -2, "cycle_next");
|
||||
lua_setglobal(L, "lunar");
|
||||
|
||||
config_manager_reload(this->cman);
|
||||
sync_config(this);
|
||||
|
||||
this->renderer.center = this->cman->cfg.space.initial_center;
|
||||
}
|
||||
|
||||
if (getenv("DISPLAY") != nullptr || getenv("WAYLAND_DISPLAY") != nullptr) {
|
||||
@@ -1227,6 +1302,11 @@ static void cleanup_wayland(LunarWM *this)
|
||||
{
|
||||
assert(this);
|
||||
|
||||
if (this->wayland.xwayland) {
|
||||
wlr_xwayland_destroy(this->wayland.xwayland);
|
||||
this->wayland.xwayland = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.new_xdg_toplevel_listener.link.prev
|
||||
|| this->wayland.new_xdg_toplevel_listener.link.next) {
|
||||
wl_list_remove(&this->wayland.new_xdg_toplevel_listener.link);
|
||||
@@ -1488,28 +1568,108 @@ static void DrawBillboardNoShear(
|
||||
{
|
||||
Rectangle const src = { 0, 0, tex.width, tex.height };
|
||||
|
||||
Vector2 const size = { scale * fabsf(src.width / src.height), scale };
|
||||
Vector2 const size = { scale * fabsf(src.width / src.height), -scale };
|
||||
Vector2 const origin = { size.x * 0.5f, size.y * 0.5f };
|
||||
|
||||
DrawBillboardPro(cam, tex, src, pos, cam.up, size, origin, 0.0f, tint);
|
||||
}
|
||||
|
||||
// pass yFlip from tl->attribs.invert_y
|
||||
static void DrawTexture3D(
|
||||
Texture2D tex, Vector3 position, Vector3 target, float scale, bool yFlip)
|
||||
{
|
||||
if (!tex.id)
|
||||
return;
|
||||
|
||||
Vector3 fwd = Vector3Normalize(Vector3Subtract(target, position));
|
||||
Vector3 upRef = (fabsf(fwd.y) > 0.99f) ? (Vector3) { 0, 0, 1 }
|
||||
: (Vector3) { 0, 1, 0 };
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(fwd, upRef));
|
||||
Vector3 up = Vector3CrossProduct(right, fwd);
|
||||
|
||||
float halfW = 0.5f * (float)tex.width * scale;
|
||||
float halfH = 0.5f * (float)tex.height * scale;
|
||||
|
||||
Vector3 tl
|
||||
= Vector3Add(Vector3Subtract(position, Vector3Scale(right, halfW)),
|
||||
Vector3Scale(up, halfH));
|
||||
Vector3 tr = Vector3Add(Vector3Add(position, Vector3Scale(right, halfW)),
|
||||
Vector3Scale(up, halfH));
|
||||
Vector3 br
|
||||
= Vector3Subtract(Vector3Add(position, Vector3Scale(right, halfW)),
|
||||
Vector3Scale(up, halfH));
|
||||
Vector3 bl
|
||||
= Vector3Subtract(Vector3Subtract(position, Vector3Scale(right, halfW)),
|
||||
Vector3Scale(up, halfH));
|
||||
|
||||
float vt = yFlip ? 1.0f : 0.0f;
|
||||
float vb = yFlip ? 0.0f : 1.0f;
|
||||
|
||||
rlDisableBackfaceCulling(); // ensure visible regardless of winding
|
||||
rlSetTexture(tex.id);
|
||||
rlBegin(RL_QUADS);
|
||||
rlNormal3f(fwd.x, fwd.y, fwd.z);
|
||||
|
||||
// TL, TR, BR, BL with canonical UVs
|
||||
rlTexCoord2f(1.0f, vt);
|
||||
rlVertex3f(tl.x, tl.y, tl.z);
|
||||
rlTexCoord2f(0.0f, vt);
|
||||
rlVertex3f(tr.x, tr.y, tr.z);
|
||||
rlTexCoord2f(0.0f, vb);
|
||||
rlVertex3f(br.x, br.y, br.z);
|
||||
rlTexCoord2f(1.0f, vb);
|
||||
rlVertex3f(bl.x, bl.y, bl.z);
|
||||
rlEnd();
|
||||
rlSetTexture(0);
|
||||
rlEnableBackfaceCulling();
|
||||
}
|
||||
|
||||
void render_hud(LunarWM *this, float /*dt*/, int hud_size)
|
||||
{
|
||||
ClearBackground((Color) { 0, 0, 0, 0 });
|
||||
|
||||
char const *txt
|
||||
= TextFormat("WAYLAND_DISPLAY=%s", getenv("WAYLAND_DISPLAY"));
|
||||
auto txt_w = MeasureText(txt, 24);
|
||||
DrawText(txt, hud_size / 2 - txt_w / 2, hud_size - 24, 24, WHITE);
|
||||
|
||||
txt = TextFormat("DISPLAY=%s", getenv("DISPLAY"));
|
||||
txt_w = MeasureText(txt, 24);
|
||||
DrawText(txt, hud_size / 2 - txt_w / 2, hud_size - 24 - 24, 24, WHITE);
|
||||
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm_info = localtime(&t);
|
||||
|
||||
int hours = tm_info->tm_hour;
|
||||
int minutes = tm_info->tm_min;
|
||||
txt = TextFormat("%02d:%02d", hours, minutes);
|
||||
txt_w = MeasureText(txt, 32);
|
||||
DrawText(txt, hud_size / 2 - txt_w / 2, 0, 32, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void render_3d(LunarWM *this, float /*dt*/)
|
||||
{
|
||||
DrawGrid(10, 1);
|
||||
|
||||
rlDisableBackfaceCulling();
|
||||
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) {
|
||||
auto *tl = this->wayland.v_toplevels[i];
|
||||
|
||||
LunarWM_Toplevel_update(tl);
|
||||
DrawBillboardNoShear(this->renderer.camera, tl->rl_texture,
|
||||
(Vector3) { 0, 1, -1.4f }, 1.0f, WHITE);
|
||||
|
||||
DrawTexture3D(tl->rl_texture,
|
||||
Vector3Add(this->renderer.center,
|
||||
(Vector3) { 0, 0, this->cman->cfg.space.radius }),
|
||||
this->renderer.center, this->cman->cfg.space.window_scale, false);
|
||||
}
|
||||
rlEnableBackfaceCulling();
|
||||
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
auto *handInfo = &this->xr.hands[h];
|
||||
for (size_t k = 0; k < XR_HAND_JOINT_COUNT_EXT; ++k) {
|
||||
auto const *jl = &handInfo->joint_locations[k]; // NOLINT
|
||||
auto const *jl = &handInfo->joint_locations[k];
|
||||
Vector3 const pos = {
|
||||
jl->pose.position.x,
|
||||
jl->pose.position.y,
|
||||
@@ -1518,6 +1678,26 @@ void render_3d(LunarWM *this, float /*dt*/)
|
||||
DrawSphere(pos, jl->radius, RED);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTextureValid(this->renderer.hud_rt.texture)) {
|
||||
rlDisableDepthTest();
|
||||
|
||||
Vector3 camPos = this->renderer.camera.position;
|
||||
Vector3 camDir = Vector3Normalize(
|
||||
Vector3Subtract(this->renderer.camera.target, camPos));
|
||||
Vector3 up = this->renderer.camera.up;
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(camDir, up));
|
||||
up = Vector3CrossProduct(right, camDir);
|
||||
|
||||
Vector3 center = Vector3Add(camPos, Vector3Scale(camDir, 0.6f));
|
||||
|
||||
float heightMeters = 0.10f;
|
||||
|
||||
DrawBillboardNoShear(this->renderer.camera,
|
||||
this->renderer.hud_rt.texture, center, heightMeters * 5, WHITE);
|
||||
|
||||
rlEnableDepthTest();
|
||||
}
|
||||
}
|
||||
|
||||
static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
||||
@@ -1598,6 +1778,19 @@ static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
||||
Matrix const viewOffL = MatrixMultiply(xr_matrix(views[0].pose), headView);
|
||||
Matrix const viewOffR = MatrixMultiply(xr_matrix(views[1].pose), headView);
|
||||
|
||||
int const hud_size = eyeH * 0.3;
|
||||
if (!IsTextureValid(this->renderer.hud_rt.texture)) {
|
||||
this->renderer.hud_rt = LoadRenderTexture(hud_size, hud_size);
|
||||
}
|
||||
|
||||
if (IsTextureValid(this->renderer.hud_rt.texture)) {
|
||||
BeginTextureMode(this->renderer.hud_rt);
|
||||
{
|
||||
render_hud(this, dt, hud_size);
|
||||
}
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
// draw
|
||||
BeginTextureMode(this->renderer.tmp_rt);
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/xwayland/xwayland.h>
|
||||
|
||||
#include <raylib.h>
|
||||
#include <raymath.h>
|
||||
#include <rlgl.h>
|
||||
|
||||
#include "Config.h"
|
||||
#include "common.h"
|
||||
|
||||
struct LunarWM;
|
||||
|
||||
@@ -48,6 +48,8 @@ typedef struct {
|
||||
} LunarWM_Keyboard;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
|
||||
struct LunarWM *server;
|
||||
|
||||
struct wl_listener commit;
|
||||
@@ -68,6 +70,7 @@ bool LunarWM_Toplevel_init(
|
||||
bool LunarWM_Toplevel_destroy(LunarWM_Toplevel *this);
|
||||
|
||||
bool LunarWM_Toplevel_update(LunarWM_Toplevel *this);
|
||||
void LunarWM_Toplevel_focus(LunarWM_Toplevel *this);
|
||||
|
||||
typedef struct {
|
||||
XrSwapchain swapchain;
|
||||
@@ -125,7 +128,10 @@ typedef struct LunarWM {
|
||||
|
||||
struct wlr_cursor *cursor;
|
||||
|
||||
struct wlr_xwayland *xwayland;
|
||||
|
||||
LunarWM_Toplevel **v_toplevels;
|
||||
int current_focus;
|
||||
} wayland;
|
||||
|
||||
struct {
|
||||
@@ -156,7 +162,10 @@ typedef struct LunarWM {
|
||||
struct {
|
||||
GLuint fbo;
|
||||
RenderTexture2D tmp_rt;
|
||||
RenderTexture2D hud_rt;
|
||||
Camera3D camera;
|
||||
|
||||
Vector3 center;
|
||||
} renderer;
|
||||
|
||||
ConfigManager *cman;
|
||||
|
||||
78
src/lua_helpers.h
Normal file
78
src/lua_helpers.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef LUA_HELPERS_H
|
||||
#define LUA_HELPERS_H
|
||||
|
||||
#include <lauxlib.h>
|
||||
#include <lua.h>
|
||||
#include <raylib.h>
|
||||
|
||||
static Vector3 lua_readVector3(lua_State *L, int index)
|
||||
{
|
||||
Vector3 v = { 0 };
|
||||
|
||||
if (!lua_istable(L, index))
|
||||
return v;
|
||||
|
||||
lua_getfield(L, index, "x");
|
||||
if (lua_isnumber(L, -1)) {
|
||||
v.x = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "y");
|
||||
v.y = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "z");
|
||||
v.z = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return v;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, index, 1);
|
||||
v.x = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, index, 2);
|
||||
v.y = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, index, 3);
|
||||
v.z = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static Vector2 lua_readVector2(lua_State *L, int index)
|
||||
{
|
||||
Vector2 v = { 0 };
|
||||
|
||||
if (!lua_istable(L, index))
|
||||
return v;
|
||||
|
||||
lua_getfield(L, index, "x");
|
||||
if (lua_isnumber(L, -1)) {
|
||||
v.x = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "y");
|
||||
v.y = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return v;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, index, 1);
|
||||
v.x = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, index, 2);
|
||||
v.y = luaL_optnumber(L, -1, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif // LUA_HELPERS_H
|
||||
Reference in New Issue
Block a user