Lib
QOLを高める
script_export.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "include/script.h"
3 #include "include/debug.h"
4 
5 namespace yappy {
6 namespace lua {
7 namespace export {
8 
9 namespace {
10 
11 template <class T>
12 inline T *getPtrFromUpvalue(lua_State *L, int uvInd)
13 {
14  int idx = lua_upvalueindex(uvInd);
15  ASSERT(lua_type(L, idx) == LUA_TLIGHTUSERDATA);
16  void *p = lua_touserdata(L, idx);
17  return static_cast<T *>(p);
18 }
19 
20 template <class F>
21 inline int exceptToLuaError(lua_State *L, F proc)
22 {
23  try {
24  return proc();
25  }
26  catch (const std::exception &ex) {
27  // push string ex.what() and throw
28  // noreturn
29  return luaL_error(L, "%s", ex.what());
30  }
31 }
32 
33 template <class T>
34 using lim = std::numeric_limits<T>;
35 
36 static_assert(lim<lua_Integer>::min() <= lim<int>::min(), "Lua type check");
37 static_assert(lim<lua_Integer>::max() >= lim<int>::max(), "Lua type check");
38 static_assert(lim<lua_Number>::max() >= lim<float>::max(), "Lua type check");
39 
40 inline int luaintToInt(lua_State *L, int arg,
41  lua_Integer val, int min, int max)
42 {
43  luaL_argcheck(L, val >= min, arg, "number too small");
44  luaL_argcheck(L, val <= max, arg, "number too large");
45  return static_cast<int>(val);
46 }
47 
48 inline int getInt(lua_State *L, int arg,
49  int min = std::numeric_limits<int>::min(),
50  int max = std::numeric_limits<int>::max())
51 {
52  lua_Integer val = luaL_checkinteger(L, arg);
53  return luaintToInt(L, arg, val, min, max);
54 }
55 
56 inline int getOptInt(lua_State *L, int arg, int def,
57  int min = std::numeric_limits<int>::min(),
58  int max = std::numeric_limits<int>::max())
59 {
60  lua_Integer val = luaL_optinteger(L, arg, def);
61  return luaintToInt(L, arg, val, min, max);
62 }
63 
64 inline float luanumToFloat(lua_State *L, int arg,
65  lua_Number val, float min, float max)
66 {
67  luaL_argcheck(L, val >= min, arg, "number too small or NaN");
68  luaL_argcheck(L, val <= max, arg, "number too large or NaN");
69  return static_cast<float>(val);
70 }
71 
72 inline double luanumToDouble(lua_State *L, int arg,
73  lua_Number val, double min, double max)
74 {
75  luaL_argcheck(L, val >= min, arg, "number too small or NaN");
76  luaL_argcheck(L, val <= max, arg, "number too large or NaN");
77  return static_cast<double>(val);
78 }
79 
80 inline float getFloat(lua_State *L, int arg,
81  float min = std::numeric_limits<float>::lowest(),
82  float max = std::numeric_limits<float>::max())
83 {
84  lua_Number val = luaL_checknumber(L, arg);
85  return luanumToFloat(L, arg, val, min, max);
86 }
87 
88 inline float getOptFloat(lua_State *L, int arg, float def,
89  float min = std::numeric_limits<float>::lowest(),
90  float max = std::numeric_limits<float>::max())
91 {
92  lua_Number val = luaL_optnumber(L, arg, def);
93  return luanumToFloat(L, arg, val, min, max);
94 }
95 
96 inline double getDouble(lua_State *L, int arg,
97  double min = std::numeric_limits<double>::lowest(),
98  double max = std::numeric_limits<double>::max())
99 {
100  lua_Number val = luaL_checknumber(L, arg);
101  return luanumToDouble(L, arg, val, min, max);
102 }
103 
104 inline double getOptDouble(lua_State *L, int arg, double def,
105  double min = std::numeric_limits<double>::lowest(),
106  double max = std::numeric_limits<double>::max())
107 {
108  lua_Number val = luaL_optnumber(L, arg, def);
109  return luanumToDouble(L, arg, val, min, max);
110 }
111 
112 } // namespace
113 
115 // "trace" table
117 
133 int trace::write(lua_State *L)
134 {
135  return exceptToLuaError(L, [L]() {
136  int argc = lua_gettop(L);
137  for (int i = 1; i <= argc; i++) {
138  const char *str = lua_tostring(L, i);
139  if (str != nullptr) {
140  debug::writeLine(str);
141  }
142  else if (lua_type(L, i) == LUA_TBOOLEAN) {
143  int b = lua_toboolean(L, i);
144  debug::writeLine(b ? "true" : "false");
145  }
146  else {
147  debug::writef("<%s>", luaL_typename(L, i));
148  }
149  }
150  return 0;
151  });
152 }
153 
166 int trace::perf(lua_State *L)
167 {
168  return exceptToLuaError(L, [L]() {
169  int argc = lua_gettop(L);
170  for (int i = 1; i <= argc; i++) {
171  const char *str = ::lua_tostring(L, i);
172  if (str != nullptr) {
173  yappy::trace::write(str);
174  }
175  else {
176  debug::writef("<%s>", luaL_typename(L, i));
177  }
178  }
179  return 0;
180  });
181 }
182 
184 // "sys" table
186 
203 int sys::include(lua_State *L)
204 {
205  return exceptToLuaError(L, [L]() {
206  auto *lua = getPtrFromUpvalue<Lua>(L, 1);
207 
208  int argc = lua_gettop(L);
209  for (int i = 1; i <= argc; i++) {
210  const char *fileName = ::lua_tostring(L, i);
211  luaL_argcheck(L, fileName != nullptr, i, "string needed");
212 
213  lua->loadFile(util::utf82wc(fileName).get(), false, false);
214  }
215  return 0;
216  });
217 }
218 
249 int sys::readFile(lua_State *L)
250 {
251  return exceptToLuaError(L, [L]() {
252  const char *fileName = luaL_checkstring(L, 1);
253 
254  FILE *tmpfp = nullptr;
255  errno_t err = ::fopen_s(&tmpfp, fileName, "r");
256  if (err == ENOENT) {
257  // return;
258  return 0;
259  }
260  else if (err != 0) {
261  luaL_error(L, "File open error: %s, %d", fileName, err);
262  }
263 
264  // return ...;
265  int retcnt = 0;
266 
267  util::FilePtr fp(tmpfp);
268  char buf[1024];
269  while (std::fgets(buf, sizeof(buf), fp.get()) != nullptr) {
270  // find new line
271  char *pnl = std::strchr(buf, '\n');
272  if (pnl != nullptr) {
273  // OK, delete '\n'
274  *pnl = '\0';
275  }
276  else {
277  // line buffer over or EOF without new line
278  // discard until NL is found or reach EOF
279  char disc[1024];
280  do {
281  if (std::fgets(disc, sizeof(disc), fp.get()) == nullptr) {
282  break;
283  }
284  } while (std::strchr(disc, '\n') == nullptr);
285  }
286  lua_pushstring(L, buf);
287  retcnt++;
288  }
289  return retcnt;
290  });
291 }
292 
317 int sys::writeFile(lua_State *L)
318 {
319  return exceptToLuaError(L, [L]() {
320  const char *fileName = luaL_checkstring(L, 1);
321 
322  FILE *tmpfp = nullptr;
323  errno_t err = ::fopen_s(&tmpfp, fileName, "w");
324  if (err != 0) {
325  luaL_error(L, "File open error: %s, %d", fileName, err);
326  }
327 
328  util::FilePtr fp(tmpfp);
329  int argc = lua_gettop(L);
330  for (int i = 2; i <= argc; i++) {
331  // if lua error, destruct fp and throw
332  const char *line = luaL_checkstring(L, i);
333  std::fputs(line, fp.get());
334  std::fputc('\n', fp.get());
335  }
336  return 0;
337  });
338 }
339 
341 // "rand" table
343 
355 int rand::generateSeed(lua_State *L)
356 {
357  return exceptToLuaError(L, [L]() {
358  unsigned int seed = framework::random::generateRandomSeed();
359  lua_pushinteger(L, seed);
360  return 1;
361  });
362 }
363 
379 int rand::setSeed(lua_State *L)
380 {
381  return exceptToLuaError(L, [L]() {
382  auto seed = static_cast<unsigned int>(luaL_checkinteger(L, 1));
384  return 0;
385  });
386 }
387 
401 int rand::nextInt(lua_State *L)
402 {
403  return exceptToLuaError(L, [L]() {
404  int a = getOptInt(L, 1, 0);
405  int b = getOptInt(L, 2, std::numeric_limits<int>::max());
406  luaL_argcheck(L, a <= b, 1, "Must be a <= b");
407 
408  int rnum = framework::random::nextInt(a, b);
409 
410  lua_pushinteger(L, rnum);
411  return 1;
412  });
413 }
414 
428 int rand::nextDouble(lua_State *L)
429 {
430  return exceptToLuaError(L, [L]() {
431  double a = getOptDouble(L, 1, 0.0);
432  double b = getOptDouble(L, 2, 1.0);
433  luaL_argcheck(L, a <= b, 1, "Must be a <= b");
434 
435  double rnum = framework::random::nextDouble(a, b);
436 
437  lua_pushnumber(L, rnum);
438  return 1;
439  });
440 }
441 
443 // "resource" table
445 
458 int resource::addTexture(lua_State *L)
459 {
460  return exceptToLuaError(L, [L]() {
461  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
462  int setId = getInt(L, 1, 0);
463  const char *resId = luaL_checkstring(L, 2);
464  const char *path = luaL_checkstring(L, 3);
465 
466  app->addTextureResource(setId, resId, util::utf82wc(path).get());
467  return 0;
468  });
469 }
470 
483 int resource::addFont(lua_State *L)
484 {
485  return exceptToLuaError(L, [L]() {
486  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
487  int setId = getInt(L, 1, 0);
488  const char *resId = luaL_checkstring(L, 2);
489  const char *fontName = luaL_checkstring(L, 3);
490  const char *startCharStr = luaL_checkstring(L, 4);
491  luaL_argcheck(L, *startCharStr != '\0', 4, "empty string is NG");
492  const char *endCharStr = luaL_checkstring(L, 4);
493  luaL_argcheck(L, *endCharStr != '\0', 5, "empty string is NG");
494  int w = getInt(L, 7, 0);
495  int h = getInt(L, 8, 0);
496 
497  wchar_t startChar = util::utf82wc(startCharStr)[0];
498  wchar_t endChar = util::utf82wc(endCharStr)[0];
499 
500  app->addFontResource(setId, resId, util::utf82wc(fontName).get(),
501  startChar, endChar, w, h);
502  return 0;
503  });
504 }
505 
518 int resource::addSe(lua_State *L)
519 {
520  return exceptToLuaError(L, [L]() {
521  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
522  int setId = getInt(L, 1, 0);
523  const char *resId = luaL_checkstring(L, 2);
524  const char *path = luaL_checkstring(L, 3);
525 
526  app->addSeResource(setId, resId, util::utf82wc(path).get());
527  return 0;
528  });
529 }
530 
543 int resource::addBgm(lua_State *L)
544 {
545  return exceptToLuaError(L, [L]() {
546  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
547  int setId = getInt(L, 1, 0);
548  const char *resId = luaL_checkstring(L, 2);
549  const char *path = luaL_checkstring(L, 3);
550 
551  app->addBgmResource(setId, resId, util::utf82wc(path).get());
552  return 0;
553  });
554 }
555 
557 // "graph" table
559 
573 int graph::getParam(lua_State *L)
574 {
575  return exceptToLuaError(L, [L]() {
576  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
577 
579  app->getGraphicsParam(&param);
580 
581  lua_pushinteger(L, param.w);
582  lua_pushinteger(L, param.h);
583  lua_pushinteger(L, param.refreshRate);
584  lua_pushboolean(L, param.vsync);
585  return 4;
586  });
587 }
588 
602 int graph::getTextureSize(lua_State *L)
603 {
604  return exceptToLuaError(L, [L]() {
605  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
606  int setId = getInt(L, 1, 0);
607  const char *resId = luaL_checkstring(L, 2);
608 
609  const auto &pTex = app->getTexture(setId, resId);
610 
611  lua_pushinteger(L, pTex->w);
612  lua_pushinteger(L, pTex->h);
613  return 2;
614  });
615 }
616 
649 int graph::drawTexture(lua_State *L)
650 {
651  return exceptToLuaError(L, [L]() {
652  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
653  int setId = getInt(L, 1, 0);
654  const char *resId = luaL_checkstring(L, 2);
655  int dx = getInt(L, 3);
656  int dy = getInt(L, 4);
657 
658  bool lrInv = lua_toboolean(L, 5) != 0;
659  bool udInv = lua_toboolean(L, 6) != 0;
660  int sx = getOptInt(L, 7, 0);
661  int sy = getOptInt(L, 8, 0);
662  int sw = getOptInt(L, 9, -1);
663  int sh = getOptInt(L, 10, -1);
664  int cx = getOptInt(L, 11, 0);
665  int cy = getOptInt(L, 12, 0);
666  float angle = getOptFloat(L, 13, 0.0f);
667  float scaleX = getOptFloat(L, 14, 1.0f);
668  float scaleY = getOptFloat(L, 15, 1.0f);
669  float alpha = getOptFloat(L, 16, 1.0f);
670 
671  const auto &pTex = app->getTexture(setId, resId);
672  app->graph().drawTexture(pTex, dx, dy, lrInv, udInv, sx, sy, sw, sh, cx, cy,
673  angle, scaleX, scaleY, alpha);
674  return 0;
675  });
676 }
677 
701 int graph::drawString(lua_State *L)
702 {
703  return exceptToLuaError(L, [L]() {
704  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
705  int setId = getInt(L, 1, 0);
706  const char *resId = luaL_checkstring(L, 2);
707  const char *str = luaL_checkstring(L, 3);
708  int dx = getInt(L, 4);
709  int dy = getInt(L, 5);
710 
711  int color = getOptInt(L, 6, 0x000000);
712  int ajustX = getOptInt(L, 7, 0);
713  float scaleX = getOptFloat(L, 8, 1.0f);
714  float scaleY = getOptFloat(L, 9, 1.0f);
715  float alpha = getOptFloat(L, 10, 1.0f);
716 
717  const auto &pFont = app->getFont(setId, resId);
718  app->graph().drawString(pFont, util::utf82wc(str).get(), dx, dy,
719  color, ajustX, scaleX, scaleY, alpha);
720  return 0;
721  });
722 }
723 
725 // "sound" table
727 
739 int sound::playSe(lua_State *L)
740 {
741  return exceptToLuaError(L, [L]() {
742  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
743  int setId = getInt(L, 1, 0);
744  const char *resId = luaL_checkstring(L, 2);
745 
746  const auto &pSoundEffect = app->getSoundEffect(setId, resId);
747  app->sound().playSoundEffect(pSoundEffect);
748  return 0;
749  });
750 }
751 
763 int sound::playBgm(lua_State *L)
764 {
765  return exceptToLuaError(L, [L]() {
766  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
767  int setId = getInt(L, 1, 0);
768  const char *resId = luaL_checkstring(L, 2);
769 
770  auto &pBgm = app->getBgm(setId, resId);
771  app->sound().playBgm(pBgm);
772  return 0;
773  });
774 }
775 
785 int sound::stopBgm(lua_State *L)
786 {
787  return exceptToLuaError(L, [L]() {
788  auto *app = getPtrFromUpvalue<framework::Application>(L, 1);
789 
790  app->sound().stopBgm();
791  return 0;
792  });
793 }
794 
795 } // namespace export
796 } // namespace lua
797 } // namespace yappy
XMMATRIX udInv
Definition: graphics.cpp:36
int nextInt(int a, int b)
Get next int random number.
Definition: framework.cpp:34
const char * str
Definition: input.cpp:197
static int addSe(lua_State *L)
効果音リソースを登録する。
double nextDouble(double a, double b)
Get next double random number.
Definition: framework.cpp:40
sy
Definition: Memo.txt:67
Debug utilities.
sw
Definition: Memo.txt:67
static int addBgm(lua_State *L)
BGMリソースを登録する。
std::unique_ptr< FILE, FileDeleter > FilePtr
unique_ptr of FILE with FileDeleter.
Definition: util.h:98
void setSeed(unsigned int seed)
Set random seed.
Definition: framework.cpp:24
void writef(const wchar_t *fmt,...) noexcept
Write debug message using format string like printf.
Definition: debug.cpp:103
static int getTextureSize(lua_State *L)
テクスチャのサイズを得る。
#define ASSERT(x)
Assertion which uses debug framework.
Definition: debug.h:18
static int nextInt(lua_State *L)
次の整数乱数を生成する。
static int playSe(lua_State *L)
効果音再生を開始する。
Definition: config.cpp:6
static int drawString(lua_State *L)
文字列を描画する。
static int readFile(lua_State *L)
ファイルを読む。
static int stopBgm(lua_State *L)
BGM 再生を停止する。
void writeLine(const wchar_t *str=L"") noexcept
Write debug string and new line.
Definition: debug.h:64
static int nextDouble(lua_State *L)
次の浮動小数点乱数を生成する。
void write(const char *str)
Write string to buffer.
Definition: debug.cpp:240
static int getParam(lua_State *L)
テクスチャのサイズを得る。
XMMATRIX lrInv
Definition: graphics.cpp:35
static int writeFile(lua_State *L)
ファイルを書く。
static int setSeed(lua_State *L)
乱数のシード値を設定する。
unsigned int generateRandomSeed()
Generate nondeterministic random number for seed.
Definition: framework.cpp:19
static int playBgm(lua_State *L)
BGM 再生を開始する。
std::unique_ptr< wchar_t[]> utf82wc(const char *in)
UTF-8 to wide char.
Definition: util.h:117
static int write(lua_State *L)
デバッグ出力する。
static int include(lua_State *L)
別の Lua ソースファイルを実行する。
static int addTexture(lua_State *L)
テクスチャリソースを登録する。
static int perf(lua_State *L)
メモリ上のバッファに高速なログ出力を行う。
static int addFont(lua_State *L)
フォントリソースを登録する。
static int generateSeed(lua_State *L)
乱数シード用の値を生成する。
static int drawTexture(lua_State *L)
テクスチャを描画する。