Initial commit

This commit is contained in:
Pavel Shevaev 2023-10-23 11:13:52 +03:00
commit 8e3d2baca6
5 changed files with 269 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
tags

19
README.md Normal file
View File

@ -0,0 +1,19 @@
This package is used for code generation of bhl2 LeoECS Lite bindings for C# using Twig templates
Here the example of bindings declaration:
@shared_tokens:{"bhl_bind":true, "bhl_ecslite_component_entity":"EcsEntity"}
struct EcsEntity
@bhl_no_new @bhl_native_class:Leopotam.EcsLite.EcsPackedEntityWithWorld @bhl_custom_rw
end
struct Velocity
@bhl_native_class:`BitGames.GamePlay.Components.Velocity` @bhl_ecslite_component
Value : Vector3
end
struct Position
@bhl_native_class:`BitGames.GamePlay.Components.Position` @bhl_ecslite_component
Value : Vector3
end

15
composer.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "bit/metagen_bhl_bind_ecslite",
"description": "bhl bindings code generation utils for LeoECS lite",
"homepage": "https://git.bit5.ru/bit/metagen_bhl_bind_ecslite",
"require": {
"php": ">=7.4",
"twig/twig" : "v3.4.3",
"bit/metagen" : "^v3.0.0"
},
"autoload": {
"files": [
"src/bind.inc.php"
]
}
}

58
src/bind.inc.php Normal file
View File

@ -0,0 +1,58 @@
<?php
namespace bhl_bind_ecslite;
use Exception;
function supported_tokens()
{
return [
'bhl_ecslite_component',
'bhl_ecslite_component_entity',
];
}
class BindEclLitePlugin implements \bhl_bind\BindPlugin
{
private $units = array();
function init(\mtgMetaInfo $meta, \Twig\Environment $twig)
{
$loader = $twig->getLoader();
$loader->setPaths(
array_merge(
$loader->getPaths(),
[__DIR__ . "/../tpl"]
)
);
//let's collect units we're responsible for
foreach($meta->getUnits() as $u)
{
if($u->object->hasToken('bhl_ecslite_component'))
{
$this->units[] = $u;
}
}
//let's remove our units from the original collection
foreach($this->units as $u)
{
$meta->delUnit($u);
}
}
function codegenDecls(\Twig\Environment $twig)
{
return '';
}
function codegenRegister(\Twig\Environment $twig)
{
$code = '';
foreach($this->units as $u)
{
if($u->object->hasToken('bhl_ecslite_component'))
$code .= $twig->render('bind_ecslite.twig', ['unit' => $u->object]);
}
return $code;
}
}

176
tpl/bind_ecslite.twig Normal file
View File

@ -0,0 +1,176 @@
{% import "bhl_bind_macro.twig" as bhl_bind %}
{%- macro reg_ecslite_component(o) ~%}
{
var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Ensure", Types.Void,
#if !BHL_FRONT
delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) {
EcsPackedEntityWithWorld e = default;
stack.PopRelease().Decode(ref e);
if (e.Unpack(out EcsWorld world, out int id) == false)
return null;
ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id);
return null;
}
#else
null
#endif
,
new FuncArgSymbol("__self", types.T("{{token(o, 'bhl_ecslite_component_entity')}}"))
);
types.ns.Define(fn);
}
{
var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Del", Types.Void,
#if !BHL_FRONT
delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) {
EcsPackedEntityWithWorld e = default;
stack.PopRelease().Decode(ref e);
if (e.Unpack(out EcsWorld world, out int id) == false)
return null;
world.GetPool<{{o.name}}>().Del(id);
return null;
}
#else
null
#endif
,
new FuncArgSymbol("__self", types.T("{{token(o, 'bhl_ecslite_component_entity')}}"))
);
types.ns.Define(fn);
}
{
var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Exists", Types.Bool,
#if !BHL_FRONT
delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) {
EcsPackedEntityWithWorld e = default;
stack.PopRelease().Decode(ref e);
var dv = bhl.Val.New(frm.vm);
if (e.Unpack(out EcsWorld world, out int id) == false)
dv.SetBool(false);
else
dv.SetBool(world.GetPool<{{o.name}}>().Has(id));
stack.Push(dv);
return null;
}
#else
null
#endif
,
new FuncArgSymbol("__self", types.T("{{token(o, 'bhl_ecslite_component_entity')}}"))
);
types.ns.Define(fn);
}
{% for f in o.getfields %}
{{ _self.ecslite_component_field(o, f) }}
{% endfor %}
{% for m in o.getfuncs %}
{{ _self.ecslite_component_func(o, m) }}
{% endfor %}
{%- endmacro -%}
{%- macro ecslite_component_field(o, f) ~%}
{
var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{f.name}}", {{f.type|bhl_type_ref}},
{%- if token_or(f, 'bhl_set', 1) != 0 ~%}
1,
{%- endif ~%}
delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) {
#if !BHL_FRONT
Val dv = null;
{%- if token_or(f, 'bhl_set', 1) != 0 ~%}
if(args_info.CountArgs() > 1)
dv = stack.Pop();
{%- endif ~%}
EcsPackedEntityWithWorld e = default;
stack.PopRelease().Decode(ref e);
if (e.Unpack(out EcsWorld world, out int id) == false)
return null;
ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id);
var v = cmp.{{f.name}};
{%- if token_or(f, 'bhl_set', 1) != 0 ~%}
if(dv != null) {
{{ bhl_bind.val2native(f.type, 'dv', 'v') }};
cmp.{{f.name}} = v;
dv.Release();
}
{%- endif ~%}
dv = Val.New(frm.vm);
{
{{ bhl_bind.native2val(f.type, 'v', 'dv') }};
}
stack.Push(dv);
#endif
return null;
},
new FuncArgSymbol("e", types.T("{{token(o, 'bhl_ecslite_component_entity')}}"))
{%- if token_or(f, 'bhl_set', 1) != 0 ~%}
, new FuncArgSymbol("v", {{f.type|bhl_type_ref}})
{%- endif ~%}
);
types.ns.Define(fn);
}
{%- endmacro -%}
{%- macro ecslite_component_func(o, m) ~%}
{
var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{m.name}}",
{{m.returntype|bhl_type_ref}},
{{ count_default_args(m) }},
#if !BHL_FRONT
delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) {
EcsPackedEntityWithWorld e = default;
{{ bhl_bind.read_args2natives(m, '__') }}
stack.PopRelease().Decode(ref e);
if (e.Unpack(out EcsWorld world, out int id) == false)
return null;
ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id);
{%~ if m.returntype %}
var return_val =
{%- endif ~%}
cmp.{{m.name}}(
{%- for arg in m.args ~%} __{{arg.name}}{% if not loop.last %},{% endif %} {%- endfor ~%}
);
{{ bhl_bind.return_val(m, 'return_val') }}
return null;
}
#else
null
#endif
, new FuncArgSymbol("__self", types.T("{{token(o, 'bhl_ecslite_component_entity')}}"))
{%- if m.args %},{% endif ~%}
{{ bhl_bind.func_decl_args(m) }}
);
types.ns.Define(fn);
}
{%- endmacro -%}
{{ _self.reg_ecslite_component(unit) }}