Added a small helper utility that can generate bindings (not automatically).

This commit is contained in:
Relintai 2023-05-29 15:16:52 +02:00
parent b289295a31
commit 651e06aa3f

View File

@ -0,0 +1,519 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "c657926f",
"metadata": {},
"outputs": [],
"source": [
"import ipywidgets as widgets"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "175bc029",
"metadata": {},
"outputs": [],
"source": [
"lcc = widgets.Label(value=\"Current c++ class:\")\n",
"tcc = widgets.Text()\n",
"\n",
"l = widgets.Label(value=\"Input:\")\n",
"ta = widgets.Textarea(layout=widgets.Layout(width='80%', height='200px'))\n",
"b = widgets.Button(description='Convert',tooltip='Convert',icon='check')\n",
"\n",
"ol = widgets.Label(value=\"Output:\")\n",
"\n",
"olh = widgets.Label(value=\"Header:\")\n",
"otah = widgets.Output(layout={'border': '1px solid black'})\n",
"\n",
"ols = widgets.Label(value=\"Source:\")\n",
"otas = widgets.Output(layout={'border': '1px solid black'})\n",
"\n",
"ool = widgets.Label(value=\"Output:\")\n",
"out = widgets.Output(layout={'border': '1px solid black'})\n",
"\n",
"vbi = widgets.VBox([ lcc, tcc, l, ta, b])\n",
"vbo = widgets.VBox([ol, olh, otah, ols, otas, ool, out])\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ddbd7a11",
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'asdsd' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [4]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtransform_input\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m():\n\u001b[1;32m 2\u001b[0m b\u001b[38;5;241m.\u001b[39mon_click(transform_input, \u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[0;32m----> 3\u001b[0m \u001b[43masdsd\u001b[49m()\n\u001b[1;32m 5\u001b[0m class_remaps \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mvoid\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mvoid\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 7\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mVariant\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpandemonium_variant\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 44\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mPoolColorArray\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpandemonium_pool_color_array\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 45\u001b[0m }\n\u001b[1;32m 47\u001b[0m class_c_no_force_ptr \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 48\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbool\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 49\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mint\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 50\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mreal_t\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 51\u001b[0m }\n",
"\u001b[0;31mNameError\u001b[0m: name 'asdsd' is not defined"
]
}
],
"source": [
"if 'transform_input' in globals():\n",
" b.on_click(transform_input, True)\n",
"\n",
"class_remaps = {\n",
" 'void': 'void',\n",
" 'Variant': 'pandemonium_variant',\n",
" 'bool': 'pandemonium_bool',\n",
" 'int': 'pandemonium_int',\n",
" 'real_t': 'pandemonium_real',\n",
" 'String': 'pandemonium_string',\n",
" 'Rect2': 'pandemonium_rect2',\n",
" 'Rect2i': 'pandemonium_rect2i',\n",
" 'Vector2': 'pandemonium_vector2',\n",
" 'Vector2i': 'pandemonium_vector2i',\n",
" 'Vector3': 'pandemonium_vector3',\n",
" 'Vector3i': 'pandemonium_vector3i',\n",
" 'Vector4': 'pandemonium_vector4',\n",
" 'Vector4i': 'pandemonium_vector4i',\n",
" 'Plane': 'pandemonium_plane',\n",
" 'Quaternion': 'pandemonium_quaternion',\n",
" 'AABB': 'pandemonium_aabb',\n",
" 'Basis': 'pandemonium_basis',\n",
" 'Transform': 'pandemonium_transform',\n",
" 'Transform2d': 'pandemonium_transform2d',\n",
" 'Projection': 'pandemonium_projection',\n",
" 'Color': 'pandemonium_color',\n",
" 'NodePath': 'pandemonium_node_path',\n",
" 'RID': 'pandemonium_rid',\n",
" 'Object': 'pandemonium_object',\n",
" 'StringName': 'pandemonium_string_name',\n",
" 'Dictionary': 'pandemonium_dictionary',\n",
" 'Array': 'pandemonium_array',\n",
" 'PoolByteArray': 'pandemonium_pool_byte_array',\n",
" 'PoolIntArray': 'pandemonium_pool_int_array',\n",
" 'PoolRealArray': 'pandemonium_pool_real_array',\n",
" 'PoolStringArray': 'pandemonium_pool_string_array',\n",
" 'PoolVector2Array': 'pandemonium_pool_vector2_array',\n",
" 'PoolVector2iArray': 'pandemonium_pool_vector2i_array',\n",
" 'PoolVector3Array': 'pandemonium_pool_vector3_array',\n",
" 'PoolVector3iArray': 'pandemonium_pool_vector3i_array',\n",
" 'PoolVector4Array': 'pandemonium_pool_vector4_array',\n",
" 'PoolVector4iArray': 'pandemonium_pool_vector4i_array',\n",
" 'PoolColorArray': 'pandemonium_pool_color_array',\n",
"}\n",
"\n",
"class_c_no_force_ptr = {\n",
" 'bool': True,\n",
" 'int': True,\n",
" 'real_t': True,\n",
"}\n",
"\n",
"METHOD_ARG_TYPE_NONE = 0\n",
"METHOD_ARG_TYPE_REFERENCE = 1\n",
"METHOD_ARG_TYPE_POINTER = 2\n",
"\n",
"def get_current_cpp_class():\n",
" return tcc.value\n",
"\n",
"def get_current_c_class():\n",
" return class_remaps[tcc.value]\n",
" \n",
"\n",
"class PMethodArg:\n",
" def __init__(self):\n",
" self.is_const = False\n",
" self.cpp_type = ''\n",
" self.cpp_arg_type = METHOD_ARG_TYPE_NONE\n",
" self.cpp_has_default = False\n",
" self.arg_name = ''\n",
" self.cpp_default_value = ''\n",
" \n",
" def is_no_force_ptr(self):\n",
" return self.cpp_type in class_c_no_force_ptr\n",
" \n",
" def get_arg_name_local(self):\n",
" return self.arg_name[2:]\n",
" \n",
" def generate_c_arg(self):\n",
" s = ', '\n",
" \n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" s += class_remaps[self.cpp_type] + ' '\n",
" \n",
" is_pointer = self.cpp_arg_type != METHOD_ARG_TYPE_NONE\n",
" \n",
" if is_pointer and self.cpp_type in class_c_no_force_ptr:\n",
" is_pointer = False\n",
" \n",
" if is_pointer:\n",
" s += '*'\n",
" \n",
" s += self.arg_name\n",
" \n",
" return s\n",
" \n",
" def generate_convert_line(self):\n",
" s = ''\n",
"\n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" if self.is_no_force_ptr():\n",
" s += self.cpp_type + ' ' + self.get_arg_name_local() + ' = ' + self.arg_name + ';'\n",
" else:\n",
" s += self.cpp_type + ' *' + self.get_arg_name_local() + ' = ('\n",
" \n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" s += self.cpp_type + ' *)' + self.arg_name + ';'\n",
" \n",
" return s\n",
" \n",
" def parse_line(self, l):\n",
" self.cpp_has_default = False\n",
" \n",
" if '=' in l:\n",
" sl = l.split('=')\n",
" \n",
" l = sl[0].strip()\n",
" self.cpp_has_default = True\n",
" self.cpp_default_value = sl[1].strip()\n",
" \n",
" \n",
" self.cpp_arg_type = METHOD_ARG_TYPE_NONE\n",
" \n",
" if '*' in l:\n",
" self.cpp_arg_type = METHOD_ARG_TYPE_POINTER\n",
" \n",
" if '&' in l:\n",
" self.cpp_arg_type = METHOD_ARG_TYPE_REFERENCE\n",
" \n",
" l = l.replace('*', '')\n",
" l = l.replace('&', '')\n",
" \n",
" spls = l.split(' ')\n",
" \n",
" self.is_const = spls[0].strip() == 'const'\n",
" \n",
" if self.is_const:\n",
" spls = spls[1:]\n",
" \n",
" with out:\n",
" print(spls)\n",
" \n",
" self.cpp_type = spls[0]\n",
" self.arg_name = spls[1]\n",
" \n",
" def __str__(self):\n",
" s = ' PMethodArg:\\n'\n",
" \n",
" s += ' is_const: ' + str(self.is_const) + '\\n'\n",
" s += ' cpp_type: ' + self.cpp_type + '\\n'\n",
" s += ' cpp_arg_type: ' + str(self.cpp_arg_type) + '\\n'\n",
" s += ' arg_name: ' + self.arg_name + '\\n'\n",
" s += ' cpp_has_default: ' + str(self.cpp_has_default) + '\\n'\n",
" s += ' cpp_default_value: ' + self.cpp_default_value + '\\n'\n",
" \n",
" return s\n",
" \n",
"\n",
"\n",
"class PMethod:\n",
" def __init__(self):\n",
" self.args = []\n",
" \n",
" self.method_name = ''\n",
"\n",
" self.cpp_return_type = ''\n",
" self.is_const = False\n",
" self.is_constructor = False\n",
" \n",
" def parse_line(self, l):\n",
" l = l.replace('//', '')\n",
" l = l.replace(';', '')\n",
" l = l.replace('inline', '')\n",
" l = l.replace('_FORCE_INLINE_', '')\n",
" l = l.strip()\n",
" \n",
" self.is_const = False\n",
" \n",
" if l.endswith('const'):\n",
" self.is_const = True\n",
" \n",
" #remove it from the string\n",
" \n",
" l = l[:-5]\n",
" \n",
" l = l.replace(')', '')\n",
" \n",
" sps = l.split('(')\n",
" \n",
" mdeffull = sps[0].strip()\n",
" margsfull = sps[1].strip()\n",
" \n",
" mds = mdeffull.split(' ')\n",
" \n",
" self.is_constructor = False\n",
" \n",
" mrettype = ''\n",
" mdef = ''\n",
" \n",
" if len(mds) == 1:\n",
" self.is_constructor = True\n",
" self.method_name = mds[0].strip()\n",
" else:\n",
" self.cpp_return_type = mds[0].strip()\n",
" self.method_name = mds[1].strip()\n",
" \n",
" margsspl = margsfull.split(',')\n",
" \n",
" for ml in margsspl:\n",
" ml = ml.strip()\n",
" \n",
" if ml == '':\n",
" continue\n",
" \n",
" a = PMethodArg()\n",
" a.parse_line(ml)\n",
" self.args.append(a)\n",
" \n",
" def get_c_return_type(self):\n",
" return class_remaps[self.cpp_return_type]\n",
" \n",
" def get_c_method_name(self):\n",
" return get_current_c_class() + '_' + self.method_name\n",
"\n",
" def generate_method_string(self):\n",
" s = ''\n",
" \n",
" s += self.get_c_return_type() + ' GDAPI ' + self.get_c_method_name() + '('\n",
" \n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" s += get_current_c_class() + ' *p_self'\n",
" \n",
" for a in self.args:\n",
" s += a.generate_c_arg()\n",
" \n",
" s += ')'\n",
" \n",
" return s\n",
" \n",
" def generate_header_string(self):\n",
" return self.generate_method_string() + ';'\n",
" \n",
" def generate_impl_string(self):\n",
" s = self.generate_method_string() + '{\\n'\n",
" \n",
" # Create dest variable at top if needed\n",
" return_needs_conversion = False\n",
" \n",
" if self.cpp_return_type != 'void':\n",
" if not self.cpp_return_type in class_c_no_force_ptr:\n",
" return_needs_conversion = True\n",
" \n",
" if return_needs_conversion:\n",
" # it needs to be explicitly converted\n",
" # Just Add dest var here\n",
" s += '\\t' + self.get_c_return_type() + ' dest;\\n'\n",
" \n",
" s += '\\t'\n",
" \n",
" # Create self local\n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" s += get_current_cpp_class() + '* self = ('\n",
" \n",
" if self.is_const:\n",
" s += 'const '\n",
" \n",
" s += get_current_cpp_class() + ' *)p_self;\\n'\n",
" \n",
" # Create param locals\n",
" self_call_args = []\n",
" \n",
" for a in self.args:\n",
" if a.is_no_force_ptr():\n",
" self_call_args.append(a.arg_name)\n",
" else:\n",
" self_call_args.append('*' + a.get_arg_name_local())\n",
" \n",
" s += '\\t' + a.generate_convert_line() + '\\n'\n",
" \n",
" # Create method call\n",
" s += '\\t'\n",
"\n",
" # We have a return type\n",
" if self.cpp_return_type != 'void':\n",
" if return_needs_conversion:\n",
" s += '*((' + self.cpp_return_type + ' *)&dest) = '\n",
" else:\n",
" s += 'return '\n",
"\n",
" s += 'self->' + self.method_name + '('\n",
" \n",
" first = True\n",
" for a in self_call_args:\n",
" if first:\n",
" first = False\n",
" s += a\n",
" else:\n",
" s += ', ' + a\n",
" \n",
" s += ');\\n'\n",
" \n",
" if self.cpp_return_type != 'void':\n",
" s += '\\treturn dest;\\n'\n",
" \n",
" s += '}'\n",
" \n",
" return s\n",
" \n",
" def __str__(self):\n",
" s = 'PMethod:\\n'\n",
" \n",
" s += ' method_name: ' + self.method_name + '\\n'\n",
" s += ' cpp_return_type: ' + self.cpp_return_type + '\\n'\n",
" s += ' is_const: ' + str(self.is_const) + '\\n'\n",
" s += ' is_constructor: ' + str(self.is_constructor) + '\\n'\n",
" \n",
" s += ' args: [\\n'\n",
" \n",
" for a in self.args:\n",
" s += str(a)\n",
" s += '\\n'\n",
" \n",
" s += ' ]'\n",
" \n",
" return s\n",
"\n",
"def transform_input(b):\n",
" with out:\n",
" out.clear_output()\n",
" \n",
" with otah:\n",
" otah.clear_output()\n",
" \n",
" with otas:\n",
" otas.clear_output()\n",
" \n",
" lines = ta.value.split('\\n')\n",
" \n",
" for l in lines:\n",
" if l.strip() == '':\n",
" with otah:\n",
" print('')\n",
" \n",
" with otas:\n",
" print('')\n",
" \n",
" continue\n",
" \n",
" with out:\n",
" print('line:')\n",
" print(l)\n",
" print('')\n",
" \n",
" method = PMethod()\n",
" method.parse_line(l)\n",
" \n",
" with otah:\n",
" print(method.generate_header_string())\n",
" \n",
" with otas:\n",
" print(method.generate_impl_string())\n",
" \n",
" with out:\n",
" print(str(method))\n",
"\n",
"\n",
"b.on_click(transform_input)"
]
},
{
"cell_type": "markdown",
"id": "3060f92f",
"metadata": {},
"source": [
"# Input"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1b472401",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"display(vbi)"
]
},
{
"cell_type": "markdown",
"id": "89053f5a",
"metadata": {},
"source": [
"# Output"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a7057b5",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"display(vbo)"
]
},
{
"cell_type": "markdown",
"id": "37dfae8d",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"id": "d86d6156",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}