| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936 |
- local codegen = require "codegen"
- local idl = codegen.idl "bgfx.idl"
- local template = [[
- /+
- + ┌==============================┐
- + │ AUTO GENERATED! DO NOT EDIT! │
- + └==============================┘
- +/
- module bgfx;
- import bindbc.common.types: c_int64, c_uint64, va_list;
- import bindbc.bgfx.config;
- static import bgfx.impl;
- $version
- alias ViewID = ushort;
- enum invalidHandle(T) = T(ushort.max);
- alias ReleaseFn = extern(C++) void function(void* ptr, void* userData) nothrow;
- $types
- pragma(inline,true) nothrow @nogc{
- /**
- Allocate a buffer to pass to bgfx. Data will be freed inside bgfx.
- Params:
- size = Size to allocate.
- */
- MemoryRef alloc(uint size){
- auto mem = bgfx.impl.alloc(__traits(parameters));
- return MemoryRef(cast(ubyte[])mem.data[0..mem.size], mem);
- }
- /**
- Allocate a buffer to pass to bgfx and copy `data` into it. Data will be freed inside bgfx.
- Params:
- data = Pointer to data to be copied.
- size = Size of data to be copied.
- */
- MemoryRef copy(const(void)* data, uint size){
- auto mem = bgfx.impl.copy(__traits(parameters));
- return MemoryRef(cast(ubyte[])mem.data[0..mem.size], mem);
- }
-
- pure @safe:
- StateBlend_ blendFuncSeparate(StateBlend_ srcRGB, StateBlend_ dstRGB, StateBlend_ srcA, StateBlend_ dstA){
- return (srcRGB | ((dstRGB) << 4)) | ((srcA | (dstA << 4)) << 8);
- }
-
- ///Blend equation separate.
- StateBlendEquation_ blendEquationSeparate(StateBlendEquation_ equationRGB, StateBlendEquation_ equationA){
- return equationRGB | (equationA << 3);
- }
-
- ///Blend function.
- StateBlend_ blendFunc(StateBlend_ src, StateBlend_ dst){ return blendFuncSeparate(src, dst, src, dst); }
-
- ///Blend equation.
- StateBlendEquation_ blendEquation(StateBlendEquation_ equation){ return blendEquationSeparate(equation, equation); }
-
- ///Utility predefined blend modes.
- enum StateBlendFunc: StateBlend_{
- ///Additive blending.
- add = blendFunc(StateBlend.one, StateBlend.one),
-
- ///Alpha blend.
- alpha = blendFunc(StateBlend.srcAlpha, StateBlend.invSrcAlpha),
-
- ///Selects darker color of blend.
- darken = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.min),
-
- ///Selects lighter color of blend.
- lighten = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.max),
-
- ///Multiplies colors.
- multiply = blendFunc(StateBlend.dstColor, StateBlend.zero),
-
- ///Opaque pixels will cover the pixels directly below them without any math or algorithm applied to them.
- normal = blendFunc(StateBlend.one, StateBlend.invSrcAlpha),
-
- ///Multiplies the inverse of the blend and base colors.
- screen = blendFunc(StateBlend.one, StateBlend.invSrcColor),
-
- ///Decreases the brightness of the base color based on the value of the blend color.
- linearBurn = blendFunc(StateBlend.dstColor, StateBlend.invDstColor) | blendEquation(StateBlendEquation.sub),
- }
-
- StateBlend_ blendFuncRTx(StateBlend_ src, StateBlend_ dst){
- return cast(uint)(src >> StateBlend.shift) | (cast(uint)(dst >> StateBlend.shift) << 4);
- }
-
- StateBlend_ blendFuncRTxE(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
- return blendFuncRTx(src, dst) | (cast(uint)(equation >> StateBlendEquation.shift) << 8);
- }
-
- StateBlend_ blendFuncRT1(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 0; }
- StateBlend_ blendFuncRT2(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 11; }
- StateBlend_ blendFuncRT3(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 22; }
-
- StateBlend_ blendFuncRT1E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
- return blendFuncRTxE(src, dst, equation) << 0;
- }
- StateBlend_ blendFuncRT2E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
- return blendFuncRTxE(src, dst, equation) << 11;
- }
- StateBlend_ blendFuncRT3E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
- return blendFuncRTxE(src, dst, equation) << 22;
- }
- }
- /**
- A wrapper around `Memory` that allows you to mutate its `data`.
- Do not create instances of this struct yourself.
- */
- struct MemoryRef{
- ubyte[] data;
- const(Memory)* memory;
- alias memory this;
- }
- $structs
- mixin(joinFnBinds((){
- FnBind[] ret = [
- $funcs
- ];
- return ret;
- }(), $membersWithFns));
- static if(!staticBinding):
- import bindbc.loader;
- debug{
- mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libDebug", "bgfxDebug", "bgfx"]), [__MODULE__, "bgfx.impl"]));
- }else{
- mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libRelease", "bgfxRelease", "bgfx"]), [__MODULE__, "bgfx.impl"]));
- }
- ]]
- 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"}
- local function contains(table, val)
- for i=1,#table do
- if table[i] == val then
- return true
- end
- end
- return false
- end
- local function hasPrefix(str, prefix)
- return prefix == "" or str:sub(1, #prefix) == prefix
- end
- local function hasSuffix(str, suffix)
- return suffix == "" or str:sub(-#suffix) == suffix
- end
- local enumTypes = {}
- local membersWithFns = ""
- local capsWords = {"Mip", "Id", "Rw", "Vb", "Ib", "Cb", "Rt", "Pci", "Srgb", "Pt", "Ccw", "2d", "3d", "Msaa"}
- local capsRepl = {
- hidpi = "hiDPI", lineaa = "lineAA", maxanisotropy = "maxAnisotropy",
- notequal = "notEqual", gequal = "gEqual", Lequal = "LEqual", lequal = "lEqual",
- decrsat = "decrSat", incrsat = "incrSat", revsub = "revSub",
- linestrip = "lineStrip", tristrip = "triStrip",
- bstencil = "bStencil", fstencil = "fStencil",
- Rmask = "RMask",
- }
- local function abbrevsToUpper(name)
- if name:len() >= 3 then
- for _, abbrev in pairs(capsWords) do
- name = name:gsub(abbrev, function(s0)
- return s0:upper()
- end)
- end
- for from, to in pairs(capsRepl) do
- name = name:gsub(from, to)
- end
- end
- return name
- end
- local function toCamelCase(name)
- if name:len() >= 3 then
- name = name:sub(0, 1) .. name:sub(2, -2):gsub("_", "") .. name:sub(-1)
- end
- if name:find("%u%u+%l") then
- name = name:gsub("(%u-)(%u%l)", function(s0, s1)
- return s0:lower() .. s1
- end)
- else
- name = (name:gsub("^([^%l]*)(%l?)", function(s0, s1)
- if s1 ~= nil then
- return s0:lower() .. s1
- end
- return s0:lower()
- end))
- end
- return abbrevsToUpper(name)
- end
- -- local function toPascalCase(name)
- -- return (name:gsub("^%l", string.upper))
- -- end
- local usEnSubs = {
- color = "colour", Color = "Colour",
- rasterize = "rasterise", Rasterize = "Rasterise",
- initialize = "initialise", Initialize = "Initialise",
- normalize = "normalise", Normalize = "Normalise",
- normalized = "normalised", Normalized = "Normalised",
- ccw = "acw", CCW = "ACW",
- }
- local function toIntlEn(name)
- local change = false
- for us, intl in pairs(usEnSubs) do
- if name:find(us) then
- name = (name:gsub(us, intl))
- change = true
- end
- end
- if change then
- return name
- else
- return nil
- end
- end
- -- Unconditionally convert
- local function toIntlEnUncond(name)
- local newName = toIntlEn(name)
- if newName ~= nil then
- return newName
- end
- return name
- end
- local function hexStr(val, bits)
- local digits = bits / 4
- local str = string.format(string.format("%%0%iX", digits), val)
- local i = 4
- while i < str:len() do
- str = str:sub(0, i) .. "_" .. str:sub(i+1)
- i = i + 5
- end
-
- return "0x" .. str
- end
- local function convArray(array)
- if string.find(array, "::") then
- return string.gsub(array, "::.*", ".") .. toCamelCase(string.gsub(array, ".-::", ""))
- else
- return array
- end
- end
- local typeSubs = {
- {"uint32_t", "uint"}, {"int32_t", "int"},
- {"uint16_t", "ushort"}, {"int16_t", "short"},
- {"uint64_t", "c_uint64"}, {"int64_t", "c_int64"},
- {"uint8_t", "ubyte"}, {"int8_t", "byte"},
- {"uintptr_t", "size_t"}
- }
- local function convSomeType(arg, isFnArg)
- local type = arg.fulltype
- if type == "bx::AllocatorI*" or type == "CallbackI*" then
- type = "void*"
- else
- for _, item in ipairs(typeSubs) do
- if type:find(item[1]) then
- type = type:gsub(item[1], item[2])
- break
- end
- end
- type = type:gsub("::Enum", "") --fix enums
- type = type:gsub("%s+%*", "*") --remove spacing before `*`
-
- if isFnArg then
- for _, enum in pairs(enumTypes) do --fix C++ linkage errors
- if type == enum then
- type = string.format("bgfx.impl.%s.Enum", enum)
- else
- type = (type:gsub("(" .. enum .. ")([^A-Za-z0-9_])", function(s0, s1)
- return string.format("bgfx.impl.%s.Enum", enum) .. s1
- end))
- end
- end
- type = type:gsub("([^&]-)%s?&", "ref %1") --change `&` suffix to `ref` prefix
- if arg.array ~= nil then
- type = type .. "*" --append *
- end
- else
- type = type:gsub("([^&]-)%s?&", "%1*") --change `&` to `*`
- if arg.array ~= nil then
- type = type .. convArray(arg.array) --append [n]
- end
- end
- type = type:gsub("const%s+([A-Za-z_][A-Za-z0-9_]*)%s*%*", "const(%1)*") --change `const x*` to `const(x)*`
- type = abbrevsToUpper(type)
- end
-
- return type
- end
- local function convType(arg)
- return convSomeType(arg, false)
- end
- local function convFnArgType(arg)
- return convSomeType(arg, true)
- end
- local valSubs = {
- NULL = "null",
- UINT8_MAX = "ubyte.max",
- UINT16_MAX = "ushort.max",
- UINT32_MAX = "uint.max",
-
- BGFX_INVALID_HANDLE = "invalidHandle",
-
- BGFX_DISCARD_ALL = "Discard.all",
- BGFX_BUFFER_NONE = "Buffer.none",
- BGFX_STENCIL_NONE = "Stencil.none",
- BGFX_TEXTURE_NONE = "Texture.none",
- BGFX_SAMPLER_NONE = "Sampler.none",
- BGFX_RESET_NONE = "Reset.none",
- BGFX_SAMPLER_U_CLAMP = "SamplerU.clamp",
- BGFX_SAMPLER_V_CLAMP = "SamplerV.clamp",
- BGFX_RESOLVE_AUTO_GEN_MIPS = "Resolve.autoGenMIPs",
- ["ViewMode::Default"] = "ViewMode.default_",
- }
- local function convVal(arg, type)
- local val = string.format("%s", arg)
- for from, to in pairs(valSubs) do
- if val:find(from) then
- if from == "BGFX_INVALID_HANDLE" then
- val = val:gsub(from, to .. "!" .. type)
- else
- val = val:gsub(from, to)
- end
- end
- end
- if val:find("INT32_MAX") then
- val = val:gsub("INT32_MAX", "int.max")
- end
- val = convArray(val)
-
- return val
- end
- local function convStructType(arg)
- return convType(arg)
- end
- local function convName(name)
- name = abbrevsToUpper(name)
- if contains(dKeywords, name) then
- return name .. "_"
- end
- return name
- end
- local function convStructMember(member)
- return convStructType(member) .. " " .. convName(member.name)
- end
- local allStructs = {}
- local function genVersion()
- return "enum uint apiVersion = " .. (idl._version or 0) .. ";"
- end
- local function genStructMemberFn(func) --NOTE: this does not work on nested structs
- if func.class ~= nil and func.conly == nil and func.cppinline == nil then
- local st = allStructs[func.class]
- local attribs = ""
- if func.comments ~= nil then
- if #st.fns > 0 then
- table.insert(st.fns, "")
- end
- table.insert(st.fns, "/**")
- for _, line in ipairs(func.comments) do
- local line = line:gsub("@remarks", "Remarks:")
- line = line:gsub("@remark", "Remarks:")
- line = line:gsub("@(%l)(%l+)", function(a, b) return a:upper() .. b .. ":" end)
- table.insert(st.fns, line)
- end
-
- local hasParamsComments = false
- for _, arg in ipairs(func.args) do
- if arg.comment ~= nil then
- hasParamsComments = true
- break
- end
- end
-
- if hasParamsComments then
- table.insert(st.fns, "Params:")
- end
-
- for _, arg in ipairs(func.args) do
- if arg.comment ~= nil then
- table.insert(st.fns, "\t" .. toIntlEnUncond(convName(arg.name:sub(2))) .. " = " .. arg.comment[1])
- for i, comment in ipairs(arg.comment) do
- if i > 1 then
- table.insert(st.fns, comment)
- end
- end
- end
- end
-
- table.insert(st.fns, "*/")
- end
-
- local args = {}
- for _, arg in ipairs(func.args) do
- local def = ""
- if arg.default ~= nil then
- def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
- end
- if arg.fulltype == "..." then
- table.insert(args, "..." .. def)
- else
- table.insert(args, convFnArgType(arg) .. " " .. toIntlEnUncond(convName(arg.name:sub(2))) .. def)
- end
- end
-
- if func.const ~= nil then
- attribs = "const"
- end
- if attribs ~= "" then
- attribs = ", memAttr: q{" .. attribs .. "}"
- end
-
- table.insert(st.fns, string.format("{q{%s}, q{%s}, q{%s}, ext: `C++`%s},", convType(func.ret), func.name, table.concat(args, ", "), attribs))
- end
- end
- local converter = {}
- local yield = coroutine.yield
- local gen = {}
- gen.implFile = [[
- /+
- + ┌==============================┐
- + │ AUTO GENERATED! DO NOT EDIT! │
- + └==============================┘
- +/
- ///Do NOT import this module! Use the symbols with the same names in `bgfx/package.d` instead.
- module bgfx.impl;
- import bindbc.bgfx.config;
- import bgfx;
- package:
- mixin(joinFnBinds((){
- FnBind[] ret = [
- {q{const(Memory)*}, q{alloc}, q{uint size}, ext: `C++, "bgfx"`},
- {q{const(Memory)*}, q{copy}, q{const(void)* data, uint size}, ext: `C++, "bgfx"`},
- ];
- return ret;
- }()));
- ]]
- function gen.gen()
- local indent = ""
- local idx = 1;
- local r = template:gsub("$([a-zA-Z_]+)", function(what)
- local tmp = {}
-
- local ind_end = template:find("$"..what, idx, true)
- local ind_start = ind_end
- for j = 1, ind_end-1 do
- local i = 1+ind_end-1-j
- local c = string.sub(template, i, i)
- if c ~= ' ' and c ~= '\t' then
- ind_start = i
- break
- end
- end
-
- indent = string.sub(template, ind_start+1, ind_end-1)
-
- if what == "version" then
- return genVersion()
- elseif what == "structs" then
- for _, fn in ipairs(idl.funcs) do
- genStructMemberFn(fn)
- end
- for _, object in ipairs(idl["types"]) do
- if object.struct ~= nil and object.namespace == nil then
- local co = coroutine.create(converter[what])
- local any
- while true do
- local ok, v = coroutine.resume(co, allStructs[object.name], object.name, object.name, true, indent:len())
- assert(ok, debug.traceback(co, v))
- if not v then
- break
- end
- table.insert(tmp, v)
- any = true
- end
- if any and tmp[#tmp] ~= "" then
- table.insert(tmp, "")
- end
- end
- end
- elseif what == "membersWithFns" then
- table.insert(tmp, "\"" .. membersWithFns .. "\"")
- else
- for _, object in ipairs(idl[what]) do
- local co = coroutine.create(converter[what])
- local any
- while true do
- local ok, v = coroutine.resume(co, object)
- assert(ok, debug.traceback(co, v))
- if not v then
- break
- end
- table.insert(tmp, v)
- any = true
- end
- if any and tmp[#tmp] ~= "" then
- table.insert(tmp, "")
- end
- end
- end
- return table.concat(tmp, "\n" .. indent)
- end)
- return r
- end
- function converter.structs(st, name, fullyQualifiedName, topLvl)
- for _, line in ipairs(st.comments) do
- yield(line)
- end
-
- if topLvl then
- yield("extern(C++, \"bgfx\") struct " .. name .. "{")
- else
- yield("extern(C++) struct " .. name .. "{")
- end
-
- local subN = 0
- for _, subStruct in ipairs(st.subs) do
- subN = subN + 1
- local co = coroutine.create(converter.structs)
- while true do
- local ok, v = coroutine.resume(co, subStruct, subStruct.name, name .. "." .. subStruct.name, false)
- assert(ok, debug.traceback(co, v))
- if not v then
- break
- end
- yield("\t" .. v)
- end
- end
- if subN > 0 then
- yield("\t")
- end
-
- for _, line in ipairs(st.fields) do
- yield(line)
- end
-
- if #st.fns > 0 then
- membersWithFns = membersWithFns .. fullyQualifiedName .. ", "
- yield("\textern(D) mixin(joinFnBinds((){")
- yield("\t\tFnBind[] ret = [")
- for _, line in ipairs(st.fns) do
- yield("\t\t\t" .. line)
- end
- yield("\t\t];")
- yield("\t\treturn ret;")
- yield("\t}()));")
- end
- yield("}")
- end
- function converter.types(typ)
- if typ.comments ~= nil and not typ.struct then
- if #typ.comments == 1 then
- yield("///" .. typ.comments[1])
- else
- yield("/**")
- for _, comment in ipairs(typ.comments) do
- yield(comment)
- end
- yield("*/")
- end
- end
-
- if typ.handle then ---hnadle
- yield("extern(C++, \"bgfx\") struct " .. typ.name .. "{")
- yield("\tushort idx;")
- yield("}")
- --yield(typ.name .. " invalidHandle(){ return " .. typ.name .. "(ushort.max); }")
-
- -- For some reason, this has never worked, so I'm commenting it out just in case it does start working suddenly. :P
- --[[
- elseif typ.funcptr then
- local args = {}
- for _, arg in ipairs(typ.args) do
- if arg.fulltype == "..." then
- table.insert(args, "..." .. def)
- else
- table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
- end
- end
-
- yield(string.format("alias %s = extern(C++) %s function(%s);", typ.name, convType(typ.ret), table.concat(args, ", ")))
- --]]
- elseif typ.enum then
- local typeName = abbrevsToUpper(typ.name:gsub("::Enum", ""))
- local otherName = string.format("bgfx.impl.%s.Enum", typ.name:gsub("::Enum", ""))
-
- yield("enum " .. typeName .. ": " .. otherName .. "{")
- table.insert(enumTypes, typeName)
-
- local vals = ""
- for idx, enum in ipairs(typ.enum) do
- local comments = ""
- if enum.comment ~= nil then
- if #enum.comment == 1 then
- comments = " ///" .. enum.comment[1];
- else
- yield("\t/**")
- for _, comment in ipairs(enum.comment) do
- yield("\t" .. comment)
- end
- yield("\t*/")
- end
- end
- local name = convName(toCamelCase(enum.name))
- yield("\t" .. name .. " = " .. otherName .. "." .. name .. ",")
- vals = vals .. name .. ","
-
- local intlName = toIntlEn(enum.name)
- if intlName ~= nil then
- yield("\t" .. convName(toCamelCase(intlName)) .. " = " .. otherName .. "." .. name .. ",")
- end
- end
-
- gen.implFile = gen.implFile .. string.format([[
- extern(C++, "bgfx") package final abstract class %s{
- enum Enum{
- %scount
- }
- }
- ]], typeName, vals)
-
- yield("\t" .. "count = " .. otherName .. ".count,")
- yield("}")
-
- elseif typ.bits ~= nil then
- local typeName = convName(typ.name)
- if typeName == "Caps" then
- typeName = "CapFlags"
- end
-
- local enumType = "uint"
- if typ.bits == 64 then
- enumType = "ulong"
- elseif typ.bits == 32 then
- enumType = "uint"
- elseif typ.bits == 16 then
- enumType = "ushort"
- elseif typ.bits == 8 then
- enumType = "ubyte"
- end
-
- local maxLen = 0
- if typ.shift then
- maxLen = string.len("shift")
- elseif typ.range then
- maxLen = string.len("mask")
- end
- for _, flag in ipairs(typ.flag) do
- maxLen = math.max(maxLen, flag.name:len())
- end
-
- yield("alias " .. typeName .. "_ = " .. enumType .. ";")
- yield("enum " .. typeName .. ": " .. typeName .. "_{")
-
- local function getValOr(name)
- local t = typeName
- if typeName == "State" then
- if hasPrefix(name, "Write") then
- t = t .. name:sub(1, 5)
- name = name:sub(6)
- elseif hasPrefix(name, "DepthTest") then
- t = t .. name:sub(1, 9)
- name = name:sub(10)
- elseif hasPrefix(name, "Cull") then
- t = t .. name:sub(1, 4)
- name = name:sub(5)
- end
- elseif typeName == "Sampler" then
- if hasPrefix(name, "Min") then
- t = t .. name:sub(1, 3)
- name = name:sub(4)
- elseif hasPrefix(name, "Mag") then
- t = t .. name:sub(1, 3)
- name = name:sub(4)
- elseif hasPrefix(name, "Mip") then
- t = t .. name:sub(1, 3)
- name = name:sub(4)
- elseif hasPrefix(name, "U") then
- t = t .. name:sub(1, 1)
- name = name:sub(2)
- elseif hasPrefix(name, "V") then
- t = t .. name:sub(1, 1)
- name = name:sub(2)
- elseif hasPrefix(name, "W") then
- t = t .. name:sub(1, 1)
- name = name:sub(2)
- elseif hasPrefix(name, "Compare") then
- t = t .. name:sub(1, 7)
- name = name:sub(8)
- end
- end
- return abbrevsToUpper(t) .. "." .. convName(toCamelCase(name))
- end
-
- for idx, flag in ipairs(typ.flag) do
- local value = flag.value
- if value ~= nil then
- value = hexStr(value, typ.bits)
- else
- for _, name in ipairs(flag) do
- if value ~= nil then
- value = value .. " | " .. getValOr(name)
- else
- value = getValOr(name)
- end
- end
- end
-
- local comments = ""
- if flag.comment ~= nil then
- if #flag.comment == 1 then
- comments = " ///" .. flag.comment[1]
- else
- yield("\t/**")
- for _, comment in ipairs(flag.comment) do
- yield("\t" .. comment)
- end
- yield("\t*/")
- end
- end
-
- local name = convName(toCamelCase(flag.name))
- yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
-
- local intlName = toIntlEn(name)
- if intlName ~= nil then
- intlName = intlName
- yield("\t" .. intlName .. string.rep(" ", maxLen+2 - intlName:len()) .. "= " .. name .. ",")
- end
- end
-
- if typ.shift then
- local name = convName("shift")
- local value = typ.shift
- local comments = ""
- if typ.desc then
- comments = string.format(" ///%s bit shift", typ.desc)
- end
- yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
- end
- if typ.range then
- local name = convName("mask")
- local value = hexStr(typ.mask, typ.bits)
- local comments = ""
- if typ.desc then
- comments = string.format(" ///%s bit mask", typ.desc)
- end
- yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
- end
- yield("}")
-
- local intlName = toIntlEn(typeName)
- if intlName ~= nil then
- yield("alias " .. intlName .. " = " .. typeName .. ";")
- end
-
- if typ.helper then
- yield(string.format(
- "%s_ to%s(%s v) nothrow @nogc pure @safe{ return (v << %s) & %s; }",
- typeName,
- typeName,
- enumType,
- (typeName .. ".shift"),
- (typeName .. ".mask")))
- if intlName ~= nil then
- yield("alias to" .. intlName .. " = to" .. typeName .. ";")
- end
- end
- elseif typ.struct ~= nil then
- local st = {name = typ.name, comments = {}, fields = {}, fns = {}, subs = {}}
-
- if typ.comments ~= nil then
- if #typ.comments == 1 then
- table.insert(st.comments, "///" .. typ.comments[1])
- else
- table.insert(st.comments, "/**")
- for _, comment in ipairs(typ.comments) do
- table.insert(st.comments, comment)
- end
- table.insert(st.comments, "*/")
- end
- end
-
- for _, member in ipairs(typ.struct) do
- local comments = ""
- if member.comment ~= nil then
- if #member.comment == 1 then
- comments = " ///" .. member.comment[1]
- else
- if #st.fields > 0 then
- table.insert(st.fields, "\t")
- end
- table.insert(st.fields, "\t/**")
- for _, comment in ipairs(member.comment) do
- table.insert(st.fields, "\t" .. comment)
- end
- table.insert(st.fields, "\t*/")
- end
- end
- table.insert(st.fields, "\t" .. convStructMember(member) .. ";" .. comments)
- end
-
- if typ.ctor ~= nil and typ.name ~= "PlatformData" then
- table.insert(st.fns, "{q{void}, q{this}, q{}, ext: `C++`},")
- end
-
- if typ.namespace ~= nil then --if this is a sub-struct
- if allStructs[typ.namespace] ~= nil then
- table.insert(allStructs[typ.namespace].subs, st)
- else
- allStructs[typ.namespace] = {subs = {st}}
- end
- else --otherwise it's top-level
- if allStructs[typ.name] ~= nil then
- st.subs = allStructs[typ.name].subs
- end
- allStructs[typ.name] = st
- end
- end
- end
- function converter.funcs(func)
- if func.class == nil and func.conly == nil and func.cppinline == nil then
- local extern = "C++, \"bgfx\""
- local attribs = ""
- if (func.cfunc ~= nil and func.name ~= "init") or func.name == "alloc" or func.name == "copy" then --what the is "cfunc" even meant to mean?
- return
- end
- if func.comments ~= nil then
- yield("/**")
- for _, line in ipairs(func.comments) do
- local line = line:gsub("@remarks", "Remarks:")
- line = line:gsub("@remark", "Remarks:")
- line = line:gsub("@(%l)(%l+)", function(a, b) return a:upper() .. b .. ":" end)
- yield("* " .. line)
- end
-
- local hasParamsComments = false
- for _, arg in ipairs(func.args) do
- if arg.comment ~= nil then
- hasParamsComments = true
- break
- end
- end
-
- if hasParamsComments then
- yield("Params:")
- end
-
- for _, arg in ipairs(func.args) do
- if arg.comment ~= nil then
- yield("\t" .. toIntlEnUncond(convName(arg.name:sub(2))) .. " = " .. arg.comment[1])
- for i, comment in ipairs(arg.comment) do
- if i > 1 then
- yield(comment)
- end
- end
- end
- end
-
- yield("*/")
- end
-
- local args = {}
- for _, arg in ipairs(func.args) do
- local def = ""
- if arg.default ~= nil then
- def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
- end
- if arg.fulltype == "..." then
- table.insert(args, "..." .. def)
- else
- table.insert(args, convFnArgType(arg) .. " " .. toIntlEnUncond(convName(arg.name:sub(2))) .. def)
- end
- end
-
- if attribs ~= "" then
- attribs = ", memAttr: q{" .. attribs .. "}"
- end
-
- yield(string.format("{q{%s}, q{%s}, q{%s}, ext: `%s`%s},", convType(func.ret), func.name, table.concat(args, ", "), extern, attribs))
- end
- end
- -- printtable("idl types", idl.types)
- -- printtable("idl funcs", idl.funcs)
- function gen.write(codes, outputfile)
- local out = assert(io.open(outputfile, "wb"))
- out:write(codes)
- out:close()
- print("Generating: " .. outputfile)
- end
- if (...) == nil then
- -- run `lua bindings-d.lua` in command line
- print(gen.gen(dTemplate))
- end
- return gen
|