bindings-d.lua 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. local codegen = require "codegen"
  2. local idl = codegen.idl "bgfx.idl"
  3. local template = [[
  4. /+
  5. + ┌==============================┐
  6. + │ AUTO GENERATED! DO NOT EDIT! │
  7. + └==============================┘
  8. +/
  9. module bgfx;
  10. import bindbc.bgfx.config;
  11. import bindbc.common.types: va_list;
  12. static import bgfx.fakeenum;
  13. $version
  14. alias ViewId = ushort;
  15. enum invalidHandle(T) = T(ushort.max);
  16. alias ReleaseFn = void function(void* _ptr, void* _userData);
  17. $types
  18. pragma(inline,true) nothrow @nogc pure @safe{
  19. StateBlend_ blendFuncSeparate(StateBlend_ srcRGB, StateBlend_ dstRGB, StateBlend_ srcA, StateBlend_ dstA){
  20. return (srcRGB | ((dstRGB) << 4)) | ((srcA | (dstA << 4)) << 8);
  21. }
  22. ///Blend equation separate.
  23. StateBlendEquation_ blendEquationSeparate(StateBlendEquation_ equationRGB, StateBlendEquation_ equationA){
  24. return equationRGB | (equationA << 3);
  25. }
  26. ///Blend function.
  27. StateBlend_ blendFunc(StateBlend_ src, StateBlend_ dst){ return blendFuncSeparate(src, dst, src, dst); }
  28. ///Blend equation.
  29. StateBlendEquation_ blendEquation(StateBlendEquation_ equation){ return blendEquationSeparate(equation, equation); }
  30. ///Utility predefined blend modes.
  31. enum StateBlendFunc: StateBlend_{
  32. ///Additive blending.
  33. add = blendFunc(StateBlend.one, StateBlend.one),
  34. ///Alpha blend.
  35. alpha = blendFunc(StateBlend.srcAlpha, StateBlend.invSrcAlpha),
  36. ///Selects darker color of blend.
  37. darken = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.min),
  38. ///Selects lighter color of blend.
  39. lighten = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.max),
  40. ///Multiplies colors.
  41. multiply = blendFunc(StateBlend.dstColor, StateBlend.zero),
  42. ///Opaque pixels will cover the pixels directly below them without any math or algorithm applied to them.
  43. normal = blendFunc(StateBlend.one, StateBlend.invSrcAlpha),
  44. ///Multiplies the inverse of the blend and base colors.
  45. screen = blendFunc(StateBlend.one, StateBlend.invSrcColor),
  46. ///Decreases the brightness of the base color based on the value of the blend color.
  47. linearBurn = blendFunc(StateBlend.dstColor, StateBlend.invDstColor) | blendEquation(StateBlendEquation.sub),
  48. }
  49. StateBlend_ blendFuncRTx(StateBlend_ src, StateBlend_ dst){
  50. return cast(uint)(src >> StateBlend.shift) | (cast(uint)(dst >> StateBlend.shift) << 4);
  51. }
  52. StateBlend_ blendFuncRTxE(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
  53. return blendFuncRTx(src, dst) | (cast(uint)(equation >> StateBlendEquation.shift) << 8);
  54. }
  55. StateBlend_ blendFuncRT1(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 0; }
  56. StateBlend_ blendFuncRT2(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 11; }
  57. StateBlend_ blendFuncRT3(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 22; }
  58. StateBlend_ blendFuncRT1E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
  59. return blendFuncRTxE(src, dst, equation) << 0;
  60. }
  61. StateBlend_ blendFuncRT2E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
  62. return blendFuncRTxE(src, dst, equation) << 11;
  63. }
  64. StateBlend_ blendFuncRT3E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
  65. return blendFuncRTxE(src, dst, equation) << 22;
  66. }
  67. }
  68. $structs
  69. mixin(joinFnBinds((){
  70. string[][] ret;
  71. ret ~= makeFnBinds([
  72. $funcs
  73. ]);
  74. return ret;
  75. }(), __MODULE__, $membersWithFns));
  76. static if(!staticBinding):
  77. import bindbc.loader;
  78. debug{
  79. mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libDebug", "bgfxDebug", "bgfx"]), [__MODULE__]));
  80. }else{
  81. mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libRelease", "bgfxRelease", "bgfx"]), [__MODULE__]));
  82. }
  83. ]]
  84. local dKeywords = {"abstract", "alias", "align", "asm", "assert", "auto", "bool", "break", "byte", "case", "cast", "catch", "char", "class", "const", "continue", "dchar", "debug", "default", "delegate", "deprecated", "do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float", "for", "foreach", "foreach_reverse", "function", "goto", "if", "immutable", "import", "in", "inout", "int", "interface", "invariant", "is", "lazy", "long", "macro", "mixin", "module", "new", "nothrow", "null", "out", "override", "package", "pragma", "private", "protected", "public", "pure", "real", "ref", "return", "scope", "shared", "short", "static", "struct", "super", "switch", "synchronized", "template", "this", "throw", "true", "try", "typeid", "typeof", "ubyte", "uint", "ulong", "union", "unittest", "ushort", "version", "void", "wchar", "while", "with"}
  85. local function contains(table, val)
  86. for i=1,#table do
  87. if table[i] == val then
  88. return true
  89. end
  90. end
  91. return false
  92. end
  93. local function hasPrefix(str, prefix)
  94. return prefix == "" or str:sub(1, #prefix) == prefix
  95. end
  96. local function hasSuffix(str, suffix)
  97. return suffix == "" or str:sub(-#suffix) == suffix
  98. end
  99. local enumTypes = {}
  100. local membersWithFns = ""
  101. local capsWords = {"Mip", "Id", "Rw", "Rt", "Pci", "Srgb", "Pt", "Ccw", "2d", "3d", "Msaa"}
  102. local capsRepl = {
  103. hidpi = "hiDPI", lineaa = "lineAA", maxanisotropy = "maxAnisotropy",
  104. notequal = "notEqual", gequal = "gEqual", lequal = "lEqual",
  105. decrsat = "decrSat", incrsat = "incrSat", revsub = "revSub",
  106. linestrip = "lineStrip", tristrip = "triStrip",
  107. }
  108. local function abbrevsToUpper(name)
  109. if name:len() >= 3 then
  110. for _, abbrev in pairs(capsWords) do
  111. name = name:gsub(abbrev, function(s0)
  112. return s0:upper()
  113. end)
  114. end
  115. for from, to in pairs(capsRepl) do
  116. name = name:gsub(from, to)
  117. end
  118. end
  119. return name
  120. end
  121. local function toCamelCase(name)
  122. if name:len() >= 3 then
  123. name = name:sub(0, 1) .. name:sub(2, -2):gsub("_", "") .. name:sub(-1)
  124. end
  125. if name:find("%u%u+%l") then
  126. name = name:gsub("(%u-)(%u%l)", function(s0, s1)
  127. return s0:lower() .. s1
  128. end)
  129. else
  130. name = (name:gsub("^([^%l]*)(%l?)", function(s0, s1)
  131. if s1 ~= nil then
  132. return s0:lower() .. s1
  133. end
  134. return s0:lower()
  135. end))
  136. end
  137. return abbrevsToUpper(name)
  138. end
  139. -- local function toPascalCase(name)
  140. -- return (name:gsub("^%l", string.upper))
  141. -- end
  142. local usEnSubs = {Color = "Colour", Rasterize = "Rasterise", Initialize = "Initialise"}
  143. local function toIntlEn(name)
  144. local change = false
  145. for us, intl in pairs(usEnSubs) do
  146. if name:find(us) then
  147. name = (name:gsub(us, intl))
  148. change = true
  149. end
  150. end
  151. if change then
  152. return name
  153. else
  154. return nil
  155. end
  156. end
  157. local function hexStr(val, bits)
  158. local digits = bits / 4
  159. local str = string.format(string.format("%%0%iX", digits), val)
  160. local i = 4
  161. while i < str:len() do
  162. str = str:sub(0, i) .. "_" .. str:sub(i+1)
  163. i = i + 5
  164. end
  165. return "0x" .. str
  166. end
  167. local function convArray(array)
  168. if string.find(array, "::") then
  169. return string.gsub(array, "::.*", ".") .. toCamelCase(string.gsub(array, ".-::", ""))
  170. else
  171. return array
  172. end
  173. end
  174. local typeSubs = {
  175. uint32_t = "uint", int32_t = "int",
  176. uint16_t = "ushort", int16_t = "short",
  177. uint64_t = "ulong", int64_t = "long",
  178. uint8_t = "ubyte", int8_t = "byte",
  179. uintptr_t = "size_t"
  180. }
  181. local function convSomeType(arg, isFnArg)
  182. local type = arg.fulltype
  183. if type == "bx::AllocatorI*" or type == "CallbackI*" then
  184. type = "void*"
  185. else
  186. for from, to in pairs(typeSubs) do
  187. if type:find(from) then
  188. type = type:gsub(from, to)
  189. break
  190. end
  191. end
  192. type = type:gsub("::Enum", "") --fix enums
  193. type = type:gsub("%s+%*", "*") --remove spacing before `*`
  194. if isFnArg then
  195. for _, enum in pairs(enumTypes) do --fix C++ linkage errors
  196. if type == enum then
  197. type = string.format("bgfx.fakeenum.%s.Enum", enum)
  198. else
  199. type = (type:gsub("(" .. enum .. ")([^A-Za-z0-9_])", function(s0, s1)
  200. return string.format("bgfx.fakeenum.%s.Enum", enum) .. s1
  201. end))
  202. end
  203. end
  204. type = type:gsub("([^&]-)%s?&", "ref %1") --change `&` suffix to `ref` prefix
  205. if arg.array ~= nil then
  206. type = type .. "*" --append *
  207. end
  208. else
  209. type = type:gsub("([^&]-)%s?&", "%1*") --change `&` to `*`
  210. if arg.array ~= nil then
  211. type = type .. convArray(arg.array) --append [n]
  212. end
  213. end
  214. type = type:gsub("const%s+([A-Za-z_][A-Za-z0-9_]*)%s*%*", "const(%1)*") --change `const x*` to `const(x)*`
  215. end
  216. return type
  217. end
  218. local function convType(arg)
  219. return convSomeType(arg, false)
  220. end
  221. local function convFnArgType(arg)
  222. return convSomeType(arg, true)
  223. end
  224. local valSubs = {
  225. NULL = "null",
  226. UINT8_MAX = "ubyte.max",
  227. UINT16_MAX = "ushort.max",
  228. UINT32_MAX = "uint.max",
  229. BGFX_INVALID_HANDLE = "invalidHandle",
  230. BGFX_DISCARD_ALL = "Discard.all",
  231. BGFX_BUFFER_NONE = "Buffer.none",
  232. BGFX_STENCIL_NONE = "Stencil.none",
  233. BGFX_TEXTURE_NONE = "Texture.none",
  234. BGFX_SAMPLER_NONE = "Sampler.none",
  235. BGFX_RESET_NONE = "Reset.none",
  236. BGFX_SAMPLER_U_CLAMP = "SamplerU.clamp",
  237. BGFX_SAMPLER_V_CLAMP = "SamplerV.clamp",
  238. BGFX_RESOLVE_AUTO_GEN_MIPS = "Resolve.autoGenMIPs",
  239. ["ViewMode::Default"] = "ViewMode.default_",
  240. }
  241. local function convVal(arg, type)
  242. local val = string.format("%s", arg)
  243. for from, to in pairs(valSubs) do
  244. if val:find(from) then
  245. if from == "BGFX_INVALID_HANDLE" then
  246. val = val:gsub(from, to .. "!" .. type)
  247. else
  248. val = val:gsub(from, to)
  249. end
  250. end
  251. end
  252. if val:find("INT32_MAX") then
  253. val = val:gsub("INT32_MAX", "int.max")
  254. end
  255. val = convArray(val)
  256. return val
  257. end
  258. local function convStructType(arg)
  259. return convType(arg)
  260. end
  261. local function convName(name)
  262. name = abbrevsToUpper(name)
  263. if contains(dKeywords, name) then
  264. return name .. "_"
  265. end
  266. return name
  267. end
  268. local function convStructMember(member)
  269. return convStructType(member) .. " " .. convName(member.name)
  270. end
  271. local allStructs = {}
  272. local function genVersion()
  273. return "enum uint apiVersion = " .. (idl._version or 0) .. ";"
  274. end
  275. local function genStructMemberFn(func) --NOTE: this does not work on nested structs
  276. if func.class ~= nil and func.conly == nil then
  277. local st = allStructs[func.class]
  278. local attribs = ""
  279. if func.comments ~= nil then
  280. if #st.fns > 0 then
  281. table.insert(st.fns, "")
  282. end
  283. table.insert(st.fns, "/**")
  284. for _, line in ipairs(func.comments) do
  285. local line = line:gsub("@remarks", "Remarks:")
  286. line = line:gsub("@remark", "Remarks:")
  287. line = line:gsub("@(%l)(%l+)", function(a, b) return a:upper() .. b .. ":" end)
  288. table.insert(st.fns, line)
  289. end
  290. local hasParamsComments = false
  291. for _, arg in ipairs(func.args) do
  292. if arg.comment ~= nil then
  293. hasParamsComments = true
  294. break
  295. end
  296. end
  297. if hasParamsComments then
  298. table.insert(st.fns, "Params:")
  299. end
  300. for _, arg in ipairs(func.args) do
  301. if arg.comment ~= nil then
  302. table.insert(st.fns, "\t" .. convName(arg.name:sub(2)) .. " = " .. arg.comment[1])
  303. for i, comment in ipairs(arg.comment) do
  304. if i > 1 then
  305. table.insert(st.fns, comment)
  306. end
  307. end
  308. end
  309. end
  310. table.insert(st.fns, "*/")
  311. end
  312. local args = {}
  313. for _, arg in ipairs(func.args) do
  314. local def = ""
  315. if arg.default ~= nil then
  316. def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
  317. end
  318. if arg.fulltype == "..." then
  319. table.insert(args, "..." .. def)
  320. else
  321. table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
  322. end
  323. end
  324. if func.const ~= nil then
  325. attribs = "const"
  326. end
  327. if attribs ~= "" then
  328. attribs = ", q{" .. attribs .. "}"
  329. end
  330. table.insert(st.fns, string.format("[q{%s}, q{%s}, q{%s}, `C++`%s],", convType(func.ret), func.name, table.concat(args, ", "), attribs))
  331. end
  332. end
  333. local converter = {}
  334. local yield = coroutine.yield
  335. local gen = {}
  336. gen.fakeEnumFile = [[
  337. /+
  338. + ┌==============================┐
  339. + │ AUTO GENERATED! DO NOT EDIT! │
  340. + └==============================┘
  341. +/
  342. module bgfx.fakeenum;
  343. //NOTE: Do NOT use this module! Use the enums with the same names in `bgfx/package.d` instead.
  344. package:
  345. ]]
  346. function gen.gen()
  347. local indent = ""
  348. local idx = 1;
  349. local r = template:gsub("$([a-zA-Z_]+)", function(what)
  350. local tmp = {}
  351. local ind_end = template:find("$"..what, idx, true)
  352. local ind_start = ind_end
  353. for j = 1, ind_end-1 do
  354. local i = 1+ind_end-1-j
  355. local c = string.sub(template, i, i)
  356. if c ~= ' ' and c ~= '\t' then
  357. ind_start = i
  358. break
  359. end
  360. end
  361. indent = string.sub(template, ind_start+1, ind_end-1)
  362. if what == "version" then
  363. return genVersion()
  364. elseif what == "structs" then
  365. for _, fn in ipairs(idl.funcs) do
  366. genStructMemberFn(fn)
  367. end
  368. for name, object in pairs(allStructs) do
  369. local co = coroutine.create(converter[what])
  370. local any
  371. while true do
  372. local ok, v = coroutine.resume(co, object, name, indent:len())
  373. assert(ok, debug.traceback(co, v))
  374. if not v then
  375. break
  376. end
  377. table.insert(tmp, v)
  378. any = true
  379. end
  380. if any and tmp[#tmp] ~= "" then
  381. table.insert(tmp, "")
  382. end
  383. end
  384. elseif what == "membersWithFns" then
  385. table.insert(tmp, "\"" .. membersWithFns .. "\"")
  386. else
  387. for _, object in ipairs(idl[what]) do
  388. local co = coroutine.create(converter[what])
  389. local any
  390. while true do
  391. local ok, v = coroutine.resume(co, object)
  392. assert(ok, debug.traceback(co, v))
  393. if not v then
  394. break
  395. end
  396. table.insert(tmp, v)
  397. any = true
  398. end
  399. if any and tmp[#tmp] ~= "" then
  400. table.insert(tmp, "")
  401. end
  402. end
  403. end
  404. return table.concat(tmp, "\n" .. indent)
  405. end)
  406. return r
  407. end
  408. function converter.structs(st, name)
  409. for _, line in ipairs(st.comments) do
  410. yield(line)
  411. end
  412. yield("extern(C++, \"bgfx\") struct " .. name .. "{")
  413. local subN = 0
  414. for subName, subStruct in pairs(st.subs) do
  415. subN = subN + 1
  416. local co = coroutine.create(converter.structs)
  417. while true do
  418. local ok, v = coroutine.resume(co, subStruct, subName)
  419. assert(ok, debug.traceback(co, v))
  420. if not v then
  421. break
  422. end
  423. yield("\t" .. v)
  424. end
  425. end
  426. if subN > 0 then
  427. yield("\t")
  428. end
  429. for _, line in ipairs(st.fields) do
  430. yield(line)
  431. end
  432. if #st.fns > 0 then
  433. membersWithFns = membersWithFns .. name .. ", "
  434. yield("\textern(D) mixin(joinFnBinds((){")
  435. yield("\t\tstring[][] ret;")
  436. yield("\t\tret ~= makeFnBinds([")
  437. for _, line in ipairs(st.fns) do
  438. yield("\t\t\t" .. line)
  439. end
  440. yield("\t\t], true);")
  441. yield("\t\treturn ret;")
  442. yield("\t}(), typeof(this).stringof));")
  443. end
  444. yield("}")
  445. end
  446. function converter.types(typ)
  447. if typ.comments ~= nil and not typ.struct then
  448. if #typ.comments == 1 then
  449. yield("///" .. typ.comments[1])
  450. else
  451. yield("/**")
  452. for _, comment in ipairs(typ.comments) do
  453. yield("* " .. comment)
  454. end
  455. yield("*/")
  456. end
  457. end
  458. if typ.handle then ---hnadle
  459. yield("extern(C++, \"bgfx\") struct " .. typ.name .. "{")
  460. yield("\tushort idx;")
  461. yield("}")
  462. --yield(typ.name .. " invalidHandle(){ return " .. typ.name .. "(ushort.max); }")
  463. elseif typ.funcptr then
  464. local args = {}
  465. for _, arg in ipairs(func.args) do
  466. if arg.fulltype == "..." then
  467. table.insert(args, "..." .. def)
  468. else
  469. table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
  470. end
  471. end
  472. yield(string.format("alias %s = extern(C++) %s function(%s);", func.name, convType(func.ret), table.concat(args, ", ")))
  473. elseif typ.enum then
  474. local typeName = abbrevsToUpper(typ.name:gsub("::Enum", ""))
  475. local otherName = string.format("bgfx.fakeenum.%s.Enum", typeName)
  476. yield("")
  477. yield("enum " .. typeName .. ": " .. otherName .. "{")
  478. table.insert(enumTypes, typeName)
  479. local vals = ""
  480. for idx, enum in ipairs(typ.enum) do
  481. local comments = ""
  482. if enum.comment ~= nil then
  483. if #enum.comment == 1 then
  484. comments = " ///" .. enum.comment[1];
  485. else
  486. yield("\t/**")
  487. for _, comment in ipairs(enum.comment) do
  488. yield("\t" .. comment)
  489. end
  490. yield("\t*/")
  491. end
  492. end
  493. local name = convName(toCamelCase(enum.name))
  494. yield("\t" .. name .. " = " .. otherName .. "." .. name .. ",")
  495. vals = vals .. name .. ","
  496. local intlName = toIntlEn(enum.name)
  497. if intlName ~= nil then
  498. yield("\t" .. convName(toCamelCase(intlName)) .. " = " .. otherName .. "." .. name .. ",")
  499. end
  500. end
  501. gen.fakeEnumFile = gen.fakeEnumFile .. string.format([[
  502. extern(C++, "bgfx") package final abstract class %s{
  503. enum Enum{
  504. %scount
  505. }
  506. }
  507. ]], typeName, vals)
  508. yield("\t" .. "count = " .. otherName .. ".count,")
  509. yield("}")
  510. elseif typ.bits ~= nil then
  511. local typeName = convName(typ.name)
  512. if typeName == "Caps" then
  513. typeName = "CapFlags"
  514. end
  515. local enumType = "uint"
  516. if typ.bits == 64 then
  517. enumType = "ulong"
  518. elseif typ.bits == 32 then
  519. enumType = "uint"
  520. elseif typ.bits == 16 then
  521. enumType = "ushort"
  522. elseif typ.bits == 8 then
  523. enumType = "ubyte"
  524. end
  525. local maxLen = 0
  526. if typ.shift then
  527. maxLen = string.len("shift")
  528. elseif typ.range then
  529. maxLen = string.len("mask")
  530. end
  531. for _, flag in ipairs(typ.flag) do
  532. maxLen = math.max(maxLen, flag.name:len())
  533. end
  534. yield("alias " .. typeName .. "_ = " .. enumType .. ";")
  535. yield("enum " .. typeName .. ": " .. typeName .. "_{")
  536. local function getValOr(name)
  537. local t = typeName
  538. if typeName == "State" then
  539. if hasPrefix(name, "Write") then
  540. t = t .. name:sub(1, 5)
  541. name = name:sub(6)
  542. elseif hasPrefix(name, "DepthTest") then
  543. t = t .. name:sub(1, 9)
  544. name = name:sub(10)
  545. elseif hasPrefix(name, "Cull") then
  546. t = t .. name:sub(1, 4)
  547. name = name:sub(5)
  548. end
  549. elseif typeName == "Sampler" then
  550. if hasPrefix(name, "Min") then
  551. t = t .. name:sub(1, 3)
  552. name = name:sub(4)
  553. elseif hasPrefix(name, "Mag") then
  554. t = t .. name:sub(1, 3)
  555. name = name:sub(4)
  556. elseif hasPrefix(name, "Mip") then
  557. t = t .. name:sub(1, 3)
  558. name = name:sub(4)
  559. elseif hasPrefix(name, "U") then
  560. t = t .. name:sub(1, 1)
  561. name = name:sub(2)
  562. elseif hasPrefix(name, "V") then
  563. t = t .. name:sub(1, 1)
  564. name = name:sub(2)
  565. elseif hasPrefix(name, "W") then
  566. t = t .. name:sub(1, 1)
  567. name = name:sub(2)
  568. elseif hasPrefix(name, "Compare") then
  569. t = t .. name:sub(1, 7)
  570. name = name:sub(8)
  571. end
  572. end
  573. return abbrevsToUpper(t) .. "." .. convName(toCamelCase(name))
  574. end
  575. for idx, flag in ipairs(typ.flag) do
  576. local value = flag.value
  577. if value ~= nil then
  578. value = hexStr(value, typ.bits)
  579. else
  580. for _, name in ipairs(flag) do
  581. if value ~= nil then
  582. value = value .. " | " .. getValOr(name)
  583. else
  584. value = getValOr(name)
  585. end
  586. end
  587. end
  588. local comments = ""
  589. if flag.comment ~= nil then
  590. if #flag.comment == 1 then
  591. comments = " ///" .. flag.comment[1]
  592. else
  593. yield("/**")
  594. for _, comment in ipairs(flag.comment) do
  595. yield(comment)
  596. end
  597. yield("*/")
  598. end
  599. end
  600. local name = convName(toCamelCase(flag.name))
  601. yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
  602. local intlName = toIntlEn(flag.name)
  603. if intlName ~= nil then
  604. intlName = convName(toCamelCase(intlName))
  605. yield("\t" .. intlName .. string.rep(" ", maxLen+2 - intlName:len()) .. "= " .. name .. ",")
  606. end
  607. end
  608. if typ.shift then
  609. local name = convName("shift")
  610. local value = typ.shift
  611. local comments = ""
  612. if typ.desc then
  613. comments = string.format(" ///%s bit shift", typ.desc)
  614. end
  615. yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
  616. end
  617. if typ.range then
  618. local name = convName("mask")
  619. local value = hexStr(typ.mask, typ.bits)
  620. local comments = ""
  621. if typ.desc then
  622. comments = string.format(" ///%s bit mask", typ.desc)
  623. end
  624. yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
  625. end
  626. yield("}")
  627. local intlName = toIntlEn(typeName)
  628. if intlName ~= nil then
  629. yield("alias " .. intlName .. " = " .. typeName .. ";")
  630. end
  631. if typ.helper then
  632. yield(string.format(
  633. "%s_ to%s(%s v){ return (v << %s) & %s; }",
  634. typeName,
  635. typeName,
  636. enumType,
  637. (typeName .. ".shift"),
  638. (typeName .. ".mask")))
  639. if intlName ~= nil then
  640. yield("alias to" .. intlName .. " = to" .. typeName .. ";")
  641. end
  642. end
  643. elseif typ.struct ~= nil then
  644. local st = {comments = {}, fields = {}, fns = {}, subs = {}}
  645. if typ.comments ~= nil then
  646. if #typ.comments == 1 then
  647. table.insert(st.comments, "///" .. typ.comments[1])
  648. else
  649. table.insert(st.comments, "/**")
  650. for _, comment in ipairs(typ.comments) do
  651. table.insert(st.comments, comment)
  652. end
  653. table.insert(st.comments, "*/")
  654. end
  655. end
  656. for _, member in ipairs(typ.struct) do
  657. local comments = ""
  658. if member.comment ~= nil then
  659. if #member.comment == 1 then
  660. comments = " ///" .. member.comment[1]
  661. else
  662. if #st.fields > 0 then
  663. table.insert(st.fields, "\t")
  664. end
  665. table.insert(st.fields, "\t/**")
  666. for _, comment in ipairs(member.comment) do
  667. table.insert(st.fields, "\t" .. comment)
  668. end
  669. table.insert(st.fields, "\t*/")
  670. end
  671. end
  672. table.insert(st.fields, "\t" .. convStructMember(member) .. ";" .. comments)
  673. end
  674. if typ.ctor ~= nil and typ.name ~= "PlatformData" then
  675. table.insert(st.fns, "[q{void}, q{this}, q{}, `C++`],")
  676. end
  677. if typ.namespace ~= nil then
  678. if allStructs[typ.namespace] ~= nil then
  679. allStructs[typ.namespace].subs[typ.name] = st
  680. else
  681. allStructs[typ.namespace] = {subs = {[typ.name] = st}}
  682. end
  683. else
  684. if allStructs[typ.name] ~= nil then
  685. st.subs = allStructs[typ.name].subs
  686. end
  687. allStructs[typ.name] = st
  688. end
  689. end
  690. end
  691. function converter.funcs(func)
  692. if func.class == nil and func.conly == nil then
  693. local extern = "C++, \"bgfx\""
  694. local attribs = ""
  695. if func.cfunc ~= nil and func.name ~= "init" then --what the is "cfunc" even meant to mean?
  696. return
  697. end
  698. if func.comments ~= nil then
  699. yield("/**")
  700. for _, line in ipairs(func.comments) do
  701. local line = line:gsub("@remarks", "Remarks:")
  702. line = line:gsub("@remark", "Remarks:")
  703. line = line:gsub("@(%l)(%l+)", function(a, b) return a:upper() .. b .. ":" end)
  704. yield("* " .. line)
  705. end
  706. local hasParamsComments = false
  707. for _, arg in ipairs(func.args) do
  708. if arg.comment ~= nil then
  709. hasParamsComments = true
  710. break
  711. end
  712. end
  713. if hasParamsComments then
  714. yield("Params:")
  715. end
  716. for _, arg in ipairs(func.args) do
  717. if arg.comment ~= nil then
  718. yield("\t" .. convName(arg.name:sub(2)) .. " = " .. arg.comment[1])
  719. for i, comment in ipairs(arg.comment) do
  720. if i > 1 then
  721. yield(comment)
  722. end
  723. end
  724. end
  725. end
  726. yield("*/")
  727. end
  728. local args = {}
  729. for _, arg in ipairs(func.args) do
  730. local def = ""
  731. if arg.default ~= nil then
  732. def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
  733. end
  734. if arg.fulltype == "..." then
  735. table.insert(args, "..." .. def)
  736. else
  737. table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
  738. end
  739. end
  740. if attribs ~= "" then
  741. attribs = ", q{" .. attribs .. "}"
  742. end
  743. yield(string.format("[q{%s}, q{%s}, q{%s}, `%s`%s],", convType(func.ret), func.name, table.concat(args, ", "), extern, attribs))
  744. end
  745. end
  746. -- printtable("idl types", idl.types)
  747. -- printtable("idl funcs", idl.funcs)
  748. function gen.write(codes, outputfile)
  749. local out = assert(io.open(outputfile, "wb"))
  750. out:write(codes)
  751. out:close()
  752. print("Generating: " .. outputfile)
  753. end
  754. if (...) == nil then
  755. -- run `lua bindings-d.lua` in command line
  756. print(gen.gen(dTemplate))
  757. end
  758. return gen