bindings-d.lua 24 KB

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