Upload UI
[lsnes.git] / src / lua / gui-core.cpp
blob5e7fdf25ebd170a42e35811cdaddb86d84f9aa42
1 #include "lua/internal.hpp"
2 #include "core/window.hpp"
3 #include "library/minmax.hpp"
5 namespace
7 class lua_gui_resolution : public lua_function
9 public:
10 lua_gui_resolution() : lua_function(lua_func_misc, "gui.resolution") {}
11 int invoke(lua_state& L)
13 if(!lua_render_ctx)
14 return 0;
15 L.pushnumber(lua_render_ctx->width);
16 L.pushnumber(lua_render_ctx->height);
17 return 2;
19 } gui_resolution;
21 template<uint32_t lua_render_context::*gap, bool delta>
22 class lua_gui_set_gap : public lua_function
24 public:
25 lua_gui_set_gap(const std::string& name) : lua_function(lua_func_misc, name) {}
26 int invoke(lua_state& L)
28 if(!lua_render_ctx)
29 return 0;
30 int32_t g = L.get_numeric_argument<int32_t>(1, fname.c_str());
31 if(delta) g += lua_render_ctx->*gap;
32 if(g < 0 || g > 8192)
33 return 0; //Ignore ridiculous gap.
34 uint32_t old = lua_render_ctx->*gap;
35 lua_render_ctx->*gap = g;
36 L.pushnumber(old);
37 return 1;
41 lua_gui_set_gap<&lua_render_context::left_gap, false> lg("gui.left_gap");
42 lua_gui_set_gap<&lua_render_context::right_gap, false> rg("gui.right_gap");
43 lua_gui_set_gap<&lua_render_context::top_gap, false> tg("gui.top_gap");
44 lua_gui_set_gap<&lua_render_context::bottom_gap, false> bg("gui.bottom_gap");
45 lua_gui_set_gap<&lua_render_context::left_gap, true> dlg("gui.delta_left_gap");
46 lua_gui_set_gap<&lua_render_context::right_gap, true> drg("gui.delta_right_gap");
47 lua_gui_set_gap<&lua_render_context::top_gap, true> dtg("gui.delta_top_gap");
48 lua_gui_set_gap<&lua_render_context::bottom_gap, true> dbg("gui.delta_bottom_gap");
50 function_ptr_luafun gui_repaint(lua_func_misc, "gui.repaint", [](lua_state& L, const std::string& fname)
51 -> int {
52 lua_requests_repaint = true;
53 return 0;
54 });
56 function_ptr_luafun gui_sfupd(lua_func_misc, "gui.subframe_update", [](lua_state& L, const std::string& fname)
57 -> int {
58 lua_requests_subframe_paint = L.get_bool(1, fname.c_str());
59 return 0;
60 });
62 function_ptr_luafun gui_color(lua_func_misc, "gui.color", [](lua_state& L, const std::string& fname)
63 -> int {
64 int64_t a = 256;
65 int64_t r = L.get_numeric_argument<uint32_t>(1, fname.c_str());
66 int64_t g = L.get_numeric_argument<uint32_t>(2, fname.c_str());
67 int64_t b = L.get_numeric_argument<uint32_t>(3, fname.c_str());
68 L.get_numeric_argument<int64_t>(4, a, fname.c_str());
69 if(a > 0)
70 L.pushnumber(((256 - a) << 24) | (r << 16) | (g << 8) | b);
71 else
72 L.pushnumber(-1);
73 return 1;
74 });
76 function_ptr_luafun gui_status(lua_func_misc, "gui.status", [](lua_state& L, const std::string& fname)
77 -> int {
78 std::string name = L.get_string(1, fname.c_str());
79 std::string value = L.get_string(2, fname.c_str());
80 auto& w = platform::get_emustatus();
81 if(value == "")
82 w.erase("L[" + name + "]");
83 else
84 w.set("L[" + name + "]", value);
85 return 1;
86 });
89 //0: m
90 //1: M
91 //2: m + phue
92 //3: M - phue
93 uint8_t hsl2rgb_flags[] = {24, 52, 6, 13, 33, 19};
95 uint32_t shifthue(uint32_t color, double shift)
97 int16_t R = (color >> 16) & 0xFF;
98 int16_t G = (color >> 8) & 0xFF;
99 int16_t B = color & 0xFF;
100 int16_t m = min(R, min(G, B));
101 int16_t M = max(R, max(G, B));
102 int16_t S = M - m;
103 if(!S)
104 return color; //Grey.
105 int16_t hue;
106 if(R == M)
107 hue = G - B + 6 * S;
108 else if(G == M)
109 hue = B - R + 2 * S;
110 else
111 hue = R - G + 4 * S;
112 hue = (hue + static_cast<uint32_t>(shift * S)) % (6 * S);
113 uint32_t V[4];
114 V[0] = m;
115 V[1] = M;
116 V[2] = m + hue % S;
117 V[3] = M - hue % S;
118 uint8_t flag = hsl2rgb_flags[hue / S];
119 return (V[(flag >> 4) & 3] << 16) | (V[(flag >> 2) & 3] << 8) | (V[flag & 3]);
122 function_ptr_luafun gui_rainbow(lua_func_misc, "gui.rainbow", [](lua_state& L, const std::string& fname)
123 -> int {
124 int64_t basecolor = 0x00FF0000;
125 uint64_t step = L.get_numeric_argument<uint64_t>(1, fname.c_str());
126 int32_t steps = L.get_numeric_argument<int32_t>(2, fname.c_str());
127 L.get_numeric_argument<int64_t>(3, basecolor, fname.c_str());
128 if(!steps)
129 throw std::runtime_error("Expected nonzero steps for gui.rainbow");
130 if(basecolor < 0) {
131 //Special: Any rotation of transparent is transparent.
132 L.pushnumber(-1);
133 return 1;
135 uint32_t asteps = std::abs(steps);
136 if(steps < 0)
137 step = asteps - step % asteps; //Reverse order.
138 double hueshift = 6.0 * (step % asteps) / asteps;
139 basecolor = shifthue(basecolor & 0xFFFFFF, hueshift) | (basecolor & 0xFF000000);
140 L.pushnumber(basecolor);
141 return 1;
144 function_ptr_luafun gui_killframe(lua_func_misc, "gui.kill_frame", [](lua_state& L, const std::string& fname)
145 -> int {
146 if(lua_kill_frame)
147 *lua_kill_frame = true;