master
ブランチ master
ShaderPlayground / src / lua / luaengine.cc
32.1 KB、1036行 生 Blame 履歴
1/*
2# 076 License
3
4Copyright (c) 076 Studio LLC
5
6Permission is hereby granted to any person obtaining a copy of the software
7Shader Playground (the "Software") to use, modify, merge, copy, publish, distribute,
8sublicense, and/or sell copies of the Software, subject to the following conditions:
9
10 1. **Origin Attribution**:
11 - You must not misrepresent the origin of the Software; you must not claim
12 you created the original Software.
13 - If the Software is used in a product, you must either:
14 a. Provide clear attribution in the product's documentation, user interface,
15 or other visible areas, **OR**
16 b. Pay the original developers a fee they specify in writing.
17 2. **Usage Restriction**:
18 - The Software, or any derivative works, dependencies, or libraries
19 incorporating it, must not be used for censorship or to suppress freedom of
20 speech, expression, or creativity. Prohibited uses include, but are not
21 limited to:
22 - Censorship of so-called "hate speech", visuals, non-mainstream opinions,
23 ideas, or objective reality.
24 - Tools or systems designed to restrict access to information or
25 artistic works.
26 3. **Notice Preservation**:
27 - This license and the above copyright notice must remain intact in all copies
28 of the source code.
29
30THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
31INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
32PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
33HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
34CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
35OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37#include <glad/glad.h>
38#include <lua/luaengine.hh>
39#include <shader/shader.hh>
40#include <glfw/glfw3.h>
41#include <util/glfwpp.hh>
42#include <util/vector.hh>
43#include <util/matrix.hh>
44#include <util/random.hh>
45#include <database/locale.hh>
46#include <gui/consolelog.hh>
47
48namespace lua {
49 LuaEngine::LuaEngine(const string &code, Program *prog, Info *info)
50 : m_Code(code)
51 , m_Program(prog)
52 , m_Info(info)
53 {
54 m_Lua = MakeAPI();
55 Execute(m_Lua);
56 }
57
58 LuaEngine::~LuaEngine() {}
59
60 void LuaEngine::Reload(const string &code) {
61 m_Code = code;
62 m_Objects.clear();
63 m_Lua = MakeAPI();
64 Execute(m_Lua);
65 }
66
67 void LuaEngine::Init() {
68 if (m_IsInitialized) return;
69
70 sol::function init = m_Lua["init"];
71 if (init.valid()) {
72 sol::protected_function_result res = init();
73
74 if (!res.valid()) {
75 sol::error err = res;
76 LogError(err);
77 }
78 }
79
80 m_IsInitialized = true;
81 }
82
83 void LuaEngine::Update() {
84 if (!m_IsInitialized) return;
85
86 sol::function update = m_Lua["update"];
87 if (update.valid()) {
88 sol::protected_function_result res = update();
89
90 if (!res.valid()) {
91 sol::error err = res;
92 LogError(err);
93 }
94 }
95 }
96
97 bool LuaEngine::Validate(const string &code) {
98 try {
99 sol::load_result resSyntax = m_Lua.load(code);
100 if (!resSyntax.valid()) {
101 sol::error err = resSyntax;
102 LogError(err);
103 return false;
104 }
105
106 sol::state testApi = MakeAPI();
107 sol::load_result resApi = testApi.load(code);
108 //sol::protected_function_result resApi = testApi.safe_script(code);
109 if (!resApi.valid()) {
110 sol::error err = resApi;
111 LogError(err);
112 return false;
113 }
114
115 return true;
116 } catch (const sol::error &err) {
117 LogError(err);
118 return false;
119 }
120 }
121
122 ////////////////////
123
124 void LuaEngine::LogError(sol::error err) {
125 gui::LogEntry entry = {};
126 entry.type = gui::LogType::Error;
127 entry.text = err.what();
128 m_Info->cmd->Add(entry);
129 std::cerr << entry.text << std::endl;
130 }
131
132 void LuaEngine::LogError(const std::exception &err) {
133 gui::LogEntry entry = {};
134 entry.type = gui::LogType::Error;
135 entry.text = err.what();
136 m_Info->cmd->Add(entry);
137 std::cerr << entry.text << std::endl;
138 }
139
140 void LuaEngine::LogError(const string &err) {
141 gui::LogEntry entry = {};
142 entry.type = gui::LogType::Error;
143 entry.text = err;
144 m_Info->cmd->Add(entry);
145 std::cerr << entry.text << std::endl;
146 }
147
148 sol::state LuaEngine::MakeAPI() {
149 sol::state out;
150
151 out.open_libraries(
152 sol::lib::base,
153 sol::lib::math,
154 sol::lib::table,
155 sol::lib::string
156 );
157
158 out.new_usertype<Vector2>(
159 "Vector2",
160 "x", sol::property(
161 [](Vector2 &v) { return v.pos.x; },
162 [](Vector2 &v, f32 val) { v.pos.x = val; }
163 ),
164 "y", sol::property(
165 [](Vector2 &v) { return v.pos.y; },
166 [](Vector2 &v, f32 val) { v.pos.y = val; }
167 )
168 );
169
170 out.new_usertype<Vector2i>(
171 "Vector2i",
172 "x", sol::property(
173 [](Vector2i &v) { return v.pos.x; },
174 [](Vector2i &v, i32 val) { v.pos.x = val; }
175 ),
176 "y", sol::property(
177 [](Vector2i &v) { return v.pos.y; },
178 [](Vector2i &v, i32 val) { v.pos.y = val; }
179 )
180 );
181
182 out.new_usertype<Vector2u>(
183 "Vector2u",
184 "x", sol::property(
185 [](Vector2u &v) { return v.pos.x; },
186 [](Vector2u &v, u32 val) { v.pos.x = val; }
187 ),
188 "y", sol::property(
189 [](Vector2u &v) { return v.pos.y; },
190 [](Vector2u &v, u32 val) { v.pos.y = val; }
191 )
192 );
193
194 out.new_usertype<Vector2f>(
195 "Vector2f",
196 "x", sol::property(
197 [](Vector2f &v) { return v.pos.x; },
198 [](Vector2f &v, f32 val) { v.pos.x = val; }
199 ),
200 "y", sol::property(
201 [](Vector2f &v) { return v.pos.y; },
202 [](Vector2f &v, f32 val) { v.pos.y = val; }
203 )
204 );
205
206 out.new_usertype<Vector2d>(
207 "Vector2d",
208 "x", sol::property(
209 [](Vector2d &v) { return v.pos.x; },
210 [](Vector2d &v, i32 val) { v.pos.x = val; }
211 ),
212 "y", sol::property(
213 [](Vector2d &v) { return v.pos.y; },
214 [](Vector2d &v, f64 val) { v.pos.y = val; }
215 )
216 );
217
218 out.new_usertype<Vector3>(
219 "Vector3",
220 "x", sol::property(
221 [](Vector3 &v) { return v.pos.x; },
222 [](Vector3 &v, f32 val) { v.pos.x = val; }
223 ),
224 "y", sol::property(
225 [](Vector3 &v) { return v.pos.y; },
226 [](Vector3 &v, f32 val) { v.pos.y = val; }
227 ),
228 "z", sol::property(
229 [](Vector3 &v) { return v.pos.z; },
230 [](Vector3 &v, f32 val) { v.pos.z = val; }
231 )
232 );
233
234 out.new_usertype<Vector3i>(
235 "Vector3i",
236 "x", sol::property(
237 [](Vector3i &v) { return v.pos.x; },
238 [](Vector3i &v, i32 val) { v.pos.x = val; }
239 ),
240 "y", sol::property(
241 [](Vector3i &v) { return v.pos.y; },
242 [](Vector3i &v, i32 val) { v.pos.y = val; }
243 ),
244 "z", sol::property(
245 [](Vector3i &v) { return v.pos.z; },
246 [](Vector3i &v, i32 val) { v.pos.z = val; }
247 )
248 );
249
250 out.new_usertype<Vector3u>(
251 "Vector3u",
252 "x", sol::property(
253 [](Vector3u &v) { return v.pos.x; },
254 [](Vector3u &v, u32 val) { v.pos.x = val; }
255 ),
256 "y", sol::property(
257 [](Vector3u &v) { return v.pos.y; },
258 [](Vector3u &v, u32 val) { v.pos.y = val; }
259 ),
260 "z", sol::property(
261 [](Vector3u &v) { return v.pos.z; },
262 [](Vector3u &v, u32 val) { v.pos.z = val; }
263 )
264 );
265
266 out.new_usertype<Vector3f>(
267 "Vector3f",
268 "x", sol::property(
269 [](Vector3f &v) { return v.pos.x; },
270 [](Vector3f &v, f32 val) { v.pos.x = val; }
271 ),
272 "y", sol::property(
273 [](Vector3f &v) { return v.pos.y; },
274 [](Vector3f &v, f32 val) { v.pos.y = val; }
275 ),
276 "z", sol::property(
277 [](Vector3f &v) { return v.pos.z; },
278 [](Vector3f &v, f32 val) { v.pos.z = val; }
279 )
280 );
281
282 out.new_usertype<Vector3d>(
283 "Vector3d",
284 "x", sol::property(
285 [](Vector3d &v) { return v.pos.x; },
286 [](Vector3d &v, i32 val) { v.pos.x = val; }
287 ),
288 "y", sol::property(
289 [](Vector3d &v) { return v.pos.y; },
290 [](Vector3d &v, f64 val) { v.pos.y = val; }
291 ),
292 "z", sol::property(
293 [](Vector3d &v) { return v.pos.z; },
294 [](Vector3d &v, f64 val) { v.pos.z = val; }
295 )
296 );
297
298 out.new_usertype<Vector4>(
299 "Vector4",
300 "x", sol::property(
301 [](Vector4 &v) { return v.pos.x; },
302 [](Vector4 &v, f32 val) { v.pos.x = val; }
303 ),
304 "y", sol::property(
305 [](Vector4 &v) { return v.pos.y; },
306 [](Vector4 &v, f32 val) { v.pos.y = val; }
307 ),
308 "z", sol::property(
309 [](Vector4 &v) { return v.pos.z; },
310 [](Vector4 &v, f32 val) { v.pos.z = val; }
311 ),
312 "w", sol::property(
313 [](Vector4 &v) { return v.pos.w; },
314 [](Vector4 &v, f32 val) { v.pos.w = val; }
315 )
316 );
317
318 out.new_usertype<Vector4i>(
319 "Vector4i",
320 "x", sol::property(
321 [](Vector4i &v) { return v.pos.x; },
322 [](Vector4i &v, i32 val) { v.pos.x = val; }
323 ),
324 "y", sol::property(
325 [](Vector4i &v) { return v.pos.y; },
326 [](Vector4i &v, i32 val) { v.pos.y = val; }
327 ),
328 "z", sol::property(
329 [](Vector4i &v) { return v.pos.z; },
330 [](Vector4i &v, i32 val) { v.pos.z = val; }
331 ),
332 "w", sol::property(
333 [](Vector4i &v) { return v.pos.w; },
334 [](Vector4i &v, i32 val) { v.pos.w = val; }
335 )
336 );
337
338 out.new_usertype<Vector4u>(
339 "Vector4u",
340 "x", sol::property(
341 [](Vector4u &v) { return v.pos.x; },
342 [](Vector4u &v, u32 val) { v.pos.x = val; }
343 ),
344 "y", sol::property(
345 [](Vector4u &v) { return v.pos.y; },
346 [](Vector4u &v, u32 val) { v.pos.y = val; }
347 ),
348 "z", sol::property(
349 [](Vector4u &v) { return v.pos.z; },
350 [](Vector4u &v, u32 val) { v.pos.z = val; }
351 ),
352 "w", sol::property(
353 [](Vector4u &v) { return v.pos.w; },
354 [](Vector4u &v, u32 val) { v.pos.w = val; }
355 )
356 );
357
358 out.new_usertype<Vector4f>(
359 "Vector4f",
360 "x", sol::property(
361 [](Vector4f &v) { return v.pos.x; },
362 [](Vector4f &v, f32 val) { v.pos.x = val; }
363 ),
364 "y", sol::property(
365 [](Vector4f &v) { return v.pos.y; },
366 [](Vector4f &v, f32 val) { v.pos.y = val; }
367 ),
368 "z", sol::property(
369 [](Vector4f &v) { return v.pos.z; },
370 [](Vector4f &v, f32 val) { v.pos.z = val; }
371 ),
372 "w", sol::property(
373 [](Vector4f &v) { return v.pos.w; },
374 [](Vector4f &v, f32 val) { v.pos.w = val; }
375 )
376 );
377
378 out.new_usertype<Vector4d>(
379 "Vector4d",
380 "x", sol::property(
381 [](Vector4d &v) { return v.pos.x; },
382 [](Vector4d &v, i32 val) { v.pos.x = val; }
383 ),
384 "y", sol::property(
385 [](Vector4d &v) { return v.pos.y; },
386 [](Vector4d &v, f64 val) { v.pos.y = val; }
387 ),
388 "z", sol::property(
389 [](Vector4d &v) { return v.pos.z; },
390 [](Vector4d &v, f64 val) { v.pos.z = val; }
391 ),
392 "w", sol::property(
393 [](Vector4d &v) { return v.pos.w; },
394 [](Vector4d &v, f64 val) { v.pos.w = val; }
395 )
396 );
397
398 try {
399 BindEngine(out);
400 BindSystem(out);
401 BindIO(out);
402 BindMath(out);
403 BindGraphics(out);
404 } catch (const std::exception &e) {
405 LogError(e);
406 return {};
407 }
408
409 return out;
410 }
411
412 void LuaEngine::BindEngine(sol::state &lua) {
413 lua["le"] = lua.create_table();
414 lua["le"]["api_version"] = m_ApiVersion;
415
416 lua["le"]["log"] = [&](sol::variadic_args va) {
417 string out;
418
419 for (auto v : va) {
420 if (v.is<string>())
421 out += v.as<string>();
422 else if (v.is<i32>())
423 out += std::to_string(v.as<i32>());
424 else if (v.is<f64>())
425 out += std::to_string(v.as<f64>());
426 else if (v.is<bool>())
427 out += v.as<bool>() ? "true" : "false";
428 else if (v.is<Vector2i>())
429 out += "{" + std::to_string(v.as<Vector2i>().pos.x) + ", " + std::to_string(v.as<Vector2i>().pos.y) + "}";
430 else if (v.is<Vector2u>())
431 out += "{" + std::to_string(v.as<Vector2u>().pos.x) + ", " + std::to_string(v.as<Vector2u>().pos.y) + "}";
432 else if (v.is<Vector2f>())
433 out += "{" + std::to_string(v.as<Vector2f>().pos.x) + ", " + std::to_string(v.as<Vector2f>().pos.y) + "}";
434 else if (v.is<Vector2d>())
435 out += "{" + std::to_string(v.as<Vector2d>().pos.x) + ", " + std::to_string(v.as<Vector2d>().pos.y) + "}";
436 else if (v.is<Vector3i>())
437 out += "{" + std::to_string(v.as<Vector3i>().pos.x) + ", " + std::to_string(v.as<Vector3i>().pos.y) + ", " + std::to_string(v.as<Vector3i>().pos.z) + "}";
438 else if (v.is<Vector3u>())
439 out += "{" + std::to_string(v.as<Vector3u>().pos.x) + ", " + std::to_string(v.as<Vector3u>().pos.y) + ", " + std::to_string(v.as<Vector3u>().pos.z) + "}";
440 else if (v.is<Vector3f>())
441 out += "{" + std::to_string(v.as<Vector3f>().pos.x) + ", " + std::to_string(v.as<Vector3f>().pos.y) + ", " + std::to_string(v.as<Vector3f>().pos.z) + "}";
442 else if (v.is<Vector3d>())
443 out += "{" + std::to_string(v.as<Vector3d>().pos.x) + ", " + std::to_string(v.as<Vector3d>().pos.y) + ", " + std::to_string(v.as<Vector3d>().pos.z) + "}";
444 else if (v.is<Vector4i>())
445 out += "{" + std::to_string(v.as<Vector4i>().pos.x) + ", " + std::to_string(v.as<Vector4i>().pos.y) + ", " + std::to_string(v.as<Vector4i>().pos.z) + ", " + std::to_string(v.as<Vector4i>().pos.w) + "}";
446 else if (v.is<Vector4u>())
447 out += "{" + std::to_string(v.as<Vector4u>().pos.x) + ", " + std::to_string(v.as<Vector4u>().pos.y) + ", " + std::to_string(v.as<Vector4u>().pos.z) + ", " + std::to_string(v.as<Vector4u>().pos.w) + "}";
448 else if (v.is<Vector4f>())
449 out += "{" + std::to_string(v.as<Vector4f>().pos.x) + ", " + std::to_string(v.as<Vector4f>().pos.y) + ", " + std::to_string(v.as<Vector4f>().pos.z) + ", " + std::to_string(v.as<Vector4f>().pos.w) + "}";
450 else if (v.is<Vector4d>())
451 out += "{" + std::to_string(v.as<Vector4d>().pos.x) + ", " + std::to_string(v.as<Vector4d>().pos.y) + ", " + std::to_string(v.as<Vector4d>().pos.z) + ", " + std::to_string(v.as<Vector4d>().pos.w) + "}";
452 else if (v.get_type() == sol::type::table) {
453 sol::table t = v.as<sol::table>();
454 out += "{";
455
456 bool first = true;
457 for (auto &kv : t) {
458 if (!first) out += ", ";
459 first = false;
460
461 if (kv.second.is<i32>())
462 out += std::to_string(kv.second.as<i32>());
463 else if (kv.second.is<f64>())
464 out += std::to_string(kv.second.as<f64>());
465 else if (kv.second.is<string>())
466 out += kv.second.as<string>();
467 else
468 out += "undefined";
469 }
470
471 out += "}";
472 }
473 else
474 out += "undefined";
475
476 out += " ";
477 }
478
479 gui::LogEntry entry = {};
480 entry.type = gui::LogType::Normal;
481 entry.text = out;
482 m_Info->cmd->Add(entry);
483 std::cerr << entry.text << std::endl;
484 };
485
486 lua["le"]["sizeof"] = [&](const string &type) -> size_t {
487 static const std::unordered_map<string, size_t> sizes = {
488 { "float", sizeof(f32) },
489 { "double", sizeof(f64) },
490 { "int", sizeof(i32) },
491 { "uint", sizeof(u32) },
492
493 { "vec2", sizeof(f32) * 2 },
494 { "vec3", sizeof(f32) * 3 },
495 { "vec4", sizeof(f32) * 4 },
496
497 { "ivec2", sizeof(i32) * 2 },
498 { "ivec3", sizeof(i32) * 3 },
499 { "ivec4", sizeof(i32) * 4 },
500
501 { "uvec2", sizeof(u32) * 2 },
502 { "uvec3", sizeof(u32) * 3 },
503 { "uvec4", sizeof(u32) * 4 },
504 };
505
506 auto it = sizes.find(type);
507 if (it == sizes.end()) {
508 LogError("不正な値類: " + type);
509 return 0;
510 }
511
512 return it->second;
513 };
514 }
515
516 void LuaEngine::BindSystem(sol::state &lua) {
517 lua["le"]["sys"] = lua.create_table();
518
519 lua["le"]["sys"]["get_time"] = [&]() -> f32 {
520 return (f32)m_Info->instance->GetTime();
521 };
522
523 lua["le"]["sys"]["get_delta_time"] = [&]() -> f32 {
524 f32 now = (f32)m_Info->instance->GetTime();
525 f32 delta = now - m_LastTime;
526 m_LastTime = now;
527 if (delta > 1.f / 5) delta = 1.f / 5;
528 return delta;
529 };
530
531 lua["le"]["sys"]["get_timer_frequency"] = [&]() -> u64 {
532 return m_Info->instance->GetTimerFrequency();
533 };
534
535 lua["le"]["sys"]["get_resolution"] = [&]() -> Vector2i {
536 Vector2i size = {};
537 m_Info->window->GetSize(&size.pos.x, &size.pos.y);
538 return size;
539 };
540
541 lua["le"]["sys"]["random"] = [&](i32 min, i32 max) -> i32 {
542 return util::rand::GetRandom(min, max);
543 };
544 }
545
546 void LuaEngine::BindIO(sol::state &lua) {
547 lua["le"]["io"] = lua.create_table();
548 lua["le"]["io"]["key"] = lua.create_table();
549
550 lua["le"]["io"]["get_mouse"] = [&]() -> Vector2d {
551 Vector2d cursor{};
552 m_Info->window->GetCursorPos(&cursor.pos.x, &cursor.pos.y);
553 return cursor;
554 };
555
556 lua["le"]["io"]["key"]["is_press"] = [this](const string &key) -> bool {
557 if (!m_Info->viewportFocused) return false;
558 return m_Info->window->GetKey(StringToKey(key)) == GLFW_PRESS;
559 };
560
561 lua["le"]["io"]["key"]["is_release"] = [this](const string &key) -> bool {
562 if (!m_Info->viewportFocused) return false;
563 return m_Info->window->GetKey(StringToKey(key)) == GLFW_RELEASE;
564 };
565
566 lua["le"]["io"]["key"]["is_hold"] = [this](const string &key) -> bool {
567 if (!m_Info->viewportFocused) return false;
568 return m_Info->window->GetKey(StringToKey(key)) == GLFW_REPEAT;
569 };
570 }
571
572 void LuaEngine::BindMath(sol::state &lua) {
573 lua["le"]["math"] = lua.create_table();
574
575 lua["le"]["math"]["identity"] = [](sol::this_state ts) -> sol::table {
576 sol::state_view lua(ts);
577 Matrix4 m = mat4Identity();
578 sol::table t = lua.create_table();
579 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
580 return t;
581 };
582
583 lua["le"]["math"]["translate"] = [](sol::this_state ts, f32 x, f32 y, f32 z) -> sol::table {
584 sol::state_view lua(ts);
585 Matrix4 m = mat4Translate(x, y, z);
586 sol::table t = lua.create_table();
587 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
588 return t;
589 };
590
591 lua["le"]["math"]["scale"] = [](sol::this_state ts, f32 x, f32 y, f32 z) -> sol::table {
592 sol::state_view lua(ts);
593 Matrix4 m = mat4Scale(x, y, z);
594 sol::table t = lua.create_table();
595 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
596 return t;
597 };
598
599 lua["le"]["math"]["rotate_x"] = [](sol::this_state ts, f32 angle) -> sol::table {
600 sol::state_view lua(ts);
601 Matrix4 m = mat4RotateX(angle);
602 sol::table t = lua.create_table();
603 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
604 return t;
605 };
606
607 lua["le"]["math"]["rotate_y"] = [](sol::this_state ts, f32 angle) -> sol::table {
608 sol::state_view lua(ts);
609 Matrix4 m = mat4RotateY(angle);
610 sol::table t = lua.create_table();
611 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
612 return t;
613 };
614
615 lua["le"]["math"]["rotate_z"] = [](sol::this_state ts, f32 angle) -> sol::table {
616 sol::state_view lua(ts);
617 Matrix4 m = mat4RotateZ(angle);
618 sol::table t = lua.create_table();
619 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
620 return t;
621 };
622
623 lua["le"]["math"]["rotate"] = [](sol::this_state ts, f32 pitch, f32 yaw, f32 roll) -> sol::table {
624 sol::state_view lua(ts);
625 Matrix4 m = mat4Rotate(pitch, yaw, roll);
626 sol::table t = lua.create_table();
627 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
628 return t;
629 };
630
631 lua["le"]["math"]["perspective"] = [](sol::this_state ts, f32 fov, f32 aspect, f32 near, f32 far) -> sol::table {
632 sol::state_view lua(ts);
633 Matrix4 m = mat4Perspective(fov, aspect, near, far);
634 sol::table t = lua.create_table();
635 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
636 return t;
637 };
638
639 lua["le"]["math"]["mul"] = [](sol::this_state ts, sol::table a, sol::table b) -> sol::table {
640 sol::state_view lua(ts);
641 Matrix4 ma{}, mb{};
642
643 for (i32 i = 0; i < 16; ++i) {
644 ma.m[i] = a[i + 1];
645 mb.m[i] = b[i + 1];
646 }
647
648 Matrix4 out = mat4Mul(ma, mb);
649 sol::table t = lua.create_table();
650 for (i32 i = 0; i < 16; ++i) t[i + 1] = out.m[i];
651
652 return t;
653 };
654
655 lua["le"]["math"]["look_at"] = [](sol::this_state ts,
656 f32 ex, f32 ey, f32 ez,
657 f32 tx, f32 ty, f32 tz,
658 f32 ux, f32 uy, f32 uz) -> sol::table {
659 sol::state_view lua(ts);
660 Matrix4 m = mat4LookAt(
661 { ex, ey, ez },
662 { tx, ty, tz },
663 { ux, uy, uz }
664 );
665
666 sol::table t = lua.create_table();
667 for (i32 i = 0; i < 16; ++i) t[i + 1] = m.m[i];
668
669 return t;
670 };
671 }
672
673 void LuaEngine::BindGraphics(sol::state &lua) {
674 lua["le"]["gfx"] = lua.create_table();
675
676 lua["le"]["gfx"]["add_mesh"] = [&](sol::table t) {
677 MeshObject obj{};
678 obj.scale = { 1.f, 1.f, 1.f };
679
680 obj.mesh.vertices.clear();
681 obj.mesh.indices.clear();
682 obj.mesh.attr.clear();
683
684 sol::table verts = t["vertices"];
685 for (auto &v : verts) obj.mesh.vertices.push_back(v.second.as<f32>());
686
687 sol::table inds = t["indices"];
688 for (auto &i : inds) obj.mesh.indices.push_back(i.second.as<u32>());
689
690 sol::table attrs = t["attributes"];
691 for (auto &k : attrs) {
692 sol::table a = k.second;
693
694 sol::optional<int> location = a["location"];
695 sol::optional<int> size = a["size"];
696 sol::optional<int> stride = a["stride"];
697 sol::optional<int> offset = a["offset"];
698
699 if (!location || !size || !stride || !offset) {
700 throw std::runtime_error("メッシュアトリビュートが不正です。");
701 }
702
703 obj.mesh.attr.push_back({
704 a["location"],
705 a["size"],
706 a["stride"],
707 a["offset"],
708 });
709 }
710
711 m_Objects.push_back(obj);
712 };
713
714 lua["le"]["gfx"]["get_position"] = [&](i32 index) -> Vector3 {
715 if (index < 0 || index >= m_Objects.size()) return { 0, 0, 0 };
716 auto pos = m_Objects[index].position.pos;
717 return { pos.x, pos.y, pos.z };
718 };
719
720 lua["le"]["gfx"]["set_position"] = [&](i32 index, f32 x, f32 y, f32 z) {
721 if (index < 0 || index >= m_Objects.size()) return;
722 m_Objects[index].position = { x, y, z };
723 };
724
725 lua["le"]["gfx"]["get_rotation"] = [&](i32 index) -> Vector3 {
726 if (index < 0 || index >= m_Objects.size()) return { 0, 0, 0 };
727 auto pos = m_Objects[index].rotation.pos;
728 return { pos.x, pos.y, pos.z };
729 };
730
731 lua["le"]["gfx"]["set_rotation"] = [&](i32 index, f32 x, f32 y, f32 z) {
732 if (index < 0 || index >= m_Objects.size()) return;
733 m_Objects[index].rotation = { x, y, z };
734 };
735
736 lua["le"]["gfx"]["get_scale"] = [&](i32 index) -> Vector3 {
737 if (index < 0 || index >= m_Objects.size()) return { 0, 0, 0 };
738 auto pos = m_Objects[index].scale.pos;
739 return { pos.x, pos.y, pos.z };
740 };
741
742 lua["le"]["gfx"]["set_scale"] = [&](i32 index, f32 x, f32 y, f32 z) {
743 if (index < 0 || index >= m_Objects.size()) return;
744 m_Objects[index].scale = { x, y, z };
745 };
746
747 lua["le"]["gfx"]["set_uniform1"] = [&](const string &name, f32 x) {
748 if (!m_Program) return;
749 GLint loc = m_Program->GetUniformLocation(name);
750 if (loc == -1) {
751 LogError("ユニフォーム見つけられません: " + name);
752 return;
753 }
754 glUniform1f(loc, x);
755 };
756
757 lua["le"]["gfx"]["set_uniform2"] = [&](const string &name, f32 x, f32 y) {
758 if (!m_Program) return;
759 GLint loc = m_Program->GetUniformLocation(name);
760 if (loc == -1) {
761 LogError("ユニフォーム見つけられません: " + name);
762 return;
763 }
764 glUniform2f(loc, x, y);
765 };
766
767 lua["le"]["gfx"]["set_uniform3"] = [&](const string &name, f32 x, f32 y, f32 z) {
768 if (!m_Program) return;
769 GLint loc = m_Program->GetUniformLocation(name);
770 if (loc == -1) {
771 LogError("ユニフォーム見つけられません: " + name);
772 return;
773 }
774 glUniform3f(loc, x, y, z);
775 };
776
777 lua["le"]["gfx"]["set_uniform4"] = [&](const string &name, f32 x, f32 y, f32 z, f32 w) {
778 if (!m_Program) return;
779 GLint loc = m_Program->GetUniformLocation(name);
780 if (loc == -1) {
781 LogError("ユニフォーム見つけられません: " + name);
782 return;
783 }
784 glUniform4f(loc, x, y, z, w);
785 };
786
787 lua["le"]["gfx"]["set_uniform_float1"] = [&](const string &name, f32 x) {
788 if (!m_Program) return;
789 GLint loc = m_Program->GetUniformLocation(name);
790 if (loc == -1) {
791 LogError("ユニフォーム見つけられません: " + name);
792 return;
793 }
794 glUniform1f(loc, x);
795 };
796
797 lua["le"]["gfx"]["set_uniform_float2"] = [&](const string &name, f32 x, f32 y) {
798 if (!m_Program) return;
799 GLint loc = m_Program->GetUniformLocation(name);
800 if (loc == -1) {
801 LogError("ユニフォーム見つけられません: " + name);
802 return;
803 }
804 glUniform2f(loc, x, y);
805 };
806
807 lua["le"]["gfx"]["set_uniform_float3"] = [&](const string &name, f32 x, f32 y, f32 z) {
808 if (!m_Program) return;
809 GLint loc = m_Program->GetUniformLocation(name);
810 if (loc == -1) {
811 LogError("ユニフォーム見つけられません: " + name);
812 return;
813 }
814 glUniform3f(loc, x, y, z);
815 };
816
817 lua["le"]["gfx"]["set_uniform_float4"] = [&](const string &name, f32 x, f32 y, f32 z, f32 w) {
818 if (!m_Program) return;
819 GLint loc = m_Program->GetUniformLocation(name);
820 if (loc == -1) {
821 LogError("ユニフォーム見つけられません: " + name);
822 return;
823 }
824 glUniform4f(loc, x, y, z, w);
825 };
826
827 lua["le"]["gfx"]["set_uniform_double1"] = [&](const string &name, f64 x) {
828 if (!m_Program) return;
829 GLint loc = m_Program->GetUniformLocation(name);
830 if (loc == -1) {
831 LogError("ユニフォーム見つけられません: " + name);
832 return;
833 }
834 glUniform1d(loc, x);
835 };
836
837 lua["le"]["gfx"]["set_uniform_double2"] = [&](const string &name, f64 x, f64 y) {
838 if (!m_Program) return;
839 GLint loc = m_Program->GetUniformLocation(name);
840 if (loc == -1) {
841 LogError("ユニフォーム見つけられません: " + name);
842 return;
843 }
844 glUniform2d(loc, x, y);
845 };
846
847 lua["le"]["gfx"]["set_uniform_double3"] = [&](const string &name, f64 x, f64 y, f64 z) {
848 if (!m_Program) return;
849 GLint loc = m_Program->GetUniformLocation(name);
850 if (loc == -1) {
851 LogError("ユニフォーム見つけられません: " + name);
852 return;
853 }
854 glUniform3d(loc, x, y, z);
855 };
856
857 lua["le"]["gfx"]["set_uniform_double4"] = [&](const string &name, f64 x, f64 y, f64 z, f64 w) {
858 if (!m_Program) return;
859 GLint loc = m_Program->GetUniformLocation(name);
860 if (loc == -1) {
861 LogError("ユニフォーム見つけられません: " + name);
862 return;
863 }
864 glUniform4d(loc, x, y, z, w);
865 };
866
867 lua["le"]["gfx"]["set_uniform_int1"] = [&](const string &name, i32 x) {
868 if (!m_Program) return;
869 GLint loc = m_Program->GetUniformLocation(name);
870 if (loc == -1) {
871 LogError("ユニフォーム見つけられません: " + name);
872 return;
873 }
874 glUniform1i(loc, x);
875 };
876
877 lua["le"]["gfx"]["set_uniform_int2"] = [&](const string &name, i32 x, i32 y) {
878 if (!m_Program) return;
879 GLint loc = m_Program->GetUniformLocation(name);
880 if (loc == -1) {
881 LogError("ユニフォーム見つけられません: " + name);
882 return;
883 }
884 glUniform2i(loc, x, y);
885 };
886
887 lua["le"]["gfx"]["set_uniform_int3"] = [&](const string &name, i32 x, i32 y, i32 z) {
888 if (!m_Program) return;
889 GLint loc = m_Program->GetUniformLocation(name);
890 if (loc == -1) {
891 LogError("ユニフォーム見つけられません: " + name);
892 return;
893 }
894 glUniform3i(loc, x, y, z);
895 };
896
897 lua["le"]["gfx"]["set_uniform_int4"] = [&](const string &name, i32 x, i32 y, i32 z, i32 w) {
898 if (!m_Program) return;
899 GLint loc = m_Program->GetUniformLocation(name);
900 if (loc == -1) {
901 LogError("ユニフォーム見つけられません: " + name);
902 return;
903 }
904 glUniform4i(loc, x, y, z, w);
905 };
906
907 lua["le"]["gfx"]["set_uniform_uint1"] = [&](const string &name, u32 x) {
908 if (!m_Program) return;
909 GLint loc = m_Program->GetUniformLocation(name);
910 if (loc == -1) {
911 LogError("ユニフォーム見つけられません: " + name);
912 return;
913 }
914 glUniform1ui(loc, x);
915 };
916
917 lua["le"]["gfx"]["set_uniform_uint2"] = [&](const string &name, u32 x, u32 y) {
918 if (!m_Program) return;
919 GLint loc = m_Program->GetUniformLocation(name);
920 if (loc == -1) {
921 LogError("ユニフォーム見つけられません: " + name);
922 return;
923 }
924 glUniform2ui(loc, x, y);
925 };
926
927 lua["le"]["gfx"]["set_uniform_uint3"] = [&](const string &name, u32 x, u32 y, u32 z) {
928 if (!m_Program) return;
929 GLint loc = m_Program->GetUniformLocation(name);
930 if (loc == -1) {
931 LogError("ユニフォーム見つけられません: " + name);
932 return;
933 }
934 glUniform3ui(loc, x, y, z);
935 };
936
937 lua["le"]["gfx"]["set_uniform_uint4"] = [&](const string &name, u32 x, u32 y, u32 z, u32 w) {
938 if (!m_Program) return;
939 GLint loc = m_Program->GetUniformLocation(name);
940 if (loc == -1) {
941 LogError("ユニフォーム見つけられません: " + name);
942 return;
943 }
944 glUniform4ui(loc, x, y, z, w);
945 };
946
947 lua["le"]["gfx"]["set_uniform_vec3"] = [&](const string &name, f32 x, f32 y, f32 z) {
948 m_Program->SetUniformVec3(name, { x, y, z });
949 };
950
951 lua["le"]["gfx"]["set_uniform_mat4"] = [&](const string &name, sol::table t) {
952 if (!m_Program) return;
953 if (t.size() != 16) {
954 if (m_Info->i18n->GetCurrentLanguage().code == "ja_JP") LogError("mat4は16個の値が必要です。");
955 else LogError("mat4 must have 16 values.");
956 return;
957 }
958
959 Matrix4 mat{};
960 for (i32 i = 0; i < 16; ++i) mat.m[i] = t[i + 1];
961
962 GLint loc = m_Program->GetUniformLocation(name);
963 if (loc == -1) {
964 LogError("ユニフォーム見つけられません: " + name);
965 return;
966 }
967 glUniformMatrix4fv(loc, 1, GL_FALSE, mat.m);
968 };
969 }
970
971 void LuaEngine::Execute(sol::state &lua) {
972 sol::protected_function_result res = lua.safe_script(m_Code);
973
974 if (!res.valid()) {
975 sol::error err = res;
976 LogError(err);
977 }
978 }
979
980 i32 LuaEngine::StringToKey(const string &key) {
981 static std::unordered_map<string, i32> map = {
982 { "q", GLFW_KEY_Q },
983 { "w", GLFW_KEY_W },
984 { "e", GLFW_KEY_E },
985 { "r", GLFW_KEY_R },
986 { "t", GLFW_KEY_T },
987 { "y", GLFW_KEY_Y },
988 { "u", GLFW_KEY_U },
989 { "i", GLFW_KEY_I },
990 { "o", GLFW_KEY_O },
991 { "p", GLFW_KEY_P },
992
993 { "a", GLFW_KEY_A },
994 { "s", GLFW_KEY_S },
995 { "d", GLFW_KEY_D },
996 { "f", GLFW_KEY_F },
997 { "g", GLFW_KEY_G },
998 { "h", GLFW_KEY_H },
999 { "j", GLFW_KEY_J },
1000 { "k", GLFW_KEY_K },
1001 { "l", GLFW_KEY_L },
1002
1003 { "z", GLFW_KEY_Z },
1004 { "x", GLFW_KEY_X },
1005 { "c", GLFW_KEY_C },
1006 { "v", GLFW_KEY_V },
1007 { "b", GLFW_KEY_B },
1008 { "n", GLFW_KEY_N },
1009 { "m", GLFW_KEY_M },
1010
1011 { "1", GLFW_KEY_1 },
1012 { "2", GLFW_KEY_2 },
1013 { "3", GLFW_KEY_3 },
1014 { "4", GLFW_KEY_4 },
1015 { "5", GLFW_KEY_5 },
1016 { "6", GLFW_KEY_6 },
1017 { "7", GLFW_KEY_7 },
1018 { "8", GLFW_KEY_8 },
1019 { "9", GLFW_KEY_9 },
1020 { "0", GLFW_KEY_0 },
1021
1022 { "enter", GLFW_KEY_ENTER },
1023 { "space", GLFW_KEY_SPACE },
1024 { "shift", GLFW_KEY_LEFT_SHIFT | GLFW_KEY_RIGHT_SHIFT },
1025 { "backspace", GLFW_KEY_BACKSPACE },
1026 { "up", GLFW_KEY_UP },
1027 { "down", GLFW_KEY_DOWN },
1028 { "left", GLFW_KEY_LEFT },
1029 { "right", GLFW_KEY_RIGHT },
1030 };
1031
1032 auto it = map.find(key);
1033 if (it != map.end()) return it->second;
1034 return GLFW_KEY_UNKNOWN;
1035 }
1036} // namespace lua