2017-10-02 23:24:00 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* bindings_generator.h */
|
|
|
|
/*************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
|
|
|
/* https://godotengine.org */
|
|
|
|
/*************************************************************************/
|
2021-01-01 20:13:46 +01:00
|
|
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
|
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
2017-10-02 23:24:00 +02:00
|
|
|
/* */
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
/* the following conditions: */
|
|
|
|
/* */
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
/* */
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
/*************************************************************************/
|
2018-01-05 00:50:27 +01:00
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
#ifndef BINDINGS_GENERATOR_H
|
|
|
|
#define BINDINGS_GENERATOR_H
|
|
|
|
|
2020-11-29 04:42:06 +01:00
|
|
|
#include "core/doc_data.h"
|
2020-11-07 23:33:38 +01:00
|
|
|
#include "core/object/class_db.h"
|
|
|
|
#include "core/string/string_builder.h"
|
2020-11-29 04:42:06 +01:00
|
|
|
#include "editor/doc_tools.h"
|
2017-10-02 23:24:00 +02:00
|
|
|
#include "editor/editor_help.h"
|
|
|
|
|
2019-09-28 01:07:57 +02:00
|
|
|
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2020-11-07 23:33:38 +01:00
|
|
|
#include "core/string/ustring.h"
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
class BindingsGenerator {
|
2017-12-24 03:17:48 +01:00
|
|
|
struct ConstantInterface {
|
|
|
|
String name;
|
2018-10-18 19:41:10 +02:00
|
|
|
String proxy_name;
|
2020-11-24 10:12:55 +01:00
|
|
|
int value = 0;
|
2017-12-24 03:17:48 +01:00
|
|
|
const DocData::ConstantDoc *const_doc;
|
|
|
|
|
|
|
|
ConstantInterface() {}
|
|
|
|
|
2018-10-18 19:41:10 +02:00
|
|
|
ConstantInterface(const String &p_name, const String &p_proxy_name, int p_value) {
|
2017-12-24 03:17:48 +01:00
|
|
|
name = p_name;
|
2018-10-18 19:41:10 +02:00
|
|
|
proxy_name = p_proxy_name;
|
2017-12-24 03:17:48 +01:00
|
|
|
value = p_value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EnumInterface {
|
|
|
|
StringName cname;
|
|
|
|
List<ConstantInterface> constants;
|
|
|
|
|
|
|
|
_FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
|
|
|
|
return p_ienum.cname == cname;
|
|
|
|
}
|
|
|
|
|
|
|
|
EnumInterface() {}
|
|
|
|
|
|
|
|
EnumInterface(const StringName &p_cname) {
|
|
|
|
cname = p_cname;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PropertyInterface {
|
|
|
|
StringName cname;
|
|
|
|
String proxy_name;
|
2020-11-24 10:12:55 +01:00
|
|
|
int index = 0;
|
2017-12-24 03:17:48 +01:00
|
|
|
|
|
|
|
StringName setter;
|
|
|
|
StringName getter;
|
|
|
|
|
|
|
|
const DocData::PropertyDoc *prop_doc;
|
|
|
|
};
|
|
|
|
|
2018-04-28 22:25:25 +02:00
|
|
|
struct TypeReference {
|
|
|
|
StringName cname;
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_enum = false;
|
2018-04-28 22:25:25 +02:00
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
TypeReference() {}
|
2019-03-18 21:59:35 +01:00
|
|
|
|
|
|
|
TypeReference(const StringName &p_cname) :
|
2020-05-12 17:01:17 +02:00
|
|
|
cname(p_cname) {}
|
2018-04-28 22:25:25 +02:00
|
|
|
};
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
struct ArgumentInterface {
|
|
|
|
enum DefaultParamMode {
|
|
|
|
CONSTANT,
|
|
|
|
NULLABLE_VAL,
|
|
|
|
NULLABLE_REF
|
|
|
|
};
|
|
|
|
|
2018-04-28 22:25:25 +02:00
|
|
|
TypeReference type;
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
String name;
|
2020-05-16 04:03:05 +02:00
|
|
|
|
|
|
|
Variant def_param_value;
|
2020-05-12 17:01:17 +02:00
|
|
|
DefaultParamMode def_param_mode = CONSTANT;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2020-03-14 19:20:17 +01:00
|
|
|
/**
|
|
|
|
* Determines the expression for the parameter default value.
|
|
|
|
* Formatting elements:
|
|
|
|
* %0 or %s: [cs_type] of the argument type
|
|
|
|
*/
|
|
|
|
String default_argument;
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
ArgumentInterface() {}
|
2017-10-02 23:24:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct MethodInterface {
|
|
|
|
String name;
|
2017-12-24 03:17:48 +01:00
|
|
|
StringName cname;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Name of the C# method
|
|
|
|
*/
|
|
|
|
String proxy_name;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* [TypeInterface::name] of the return type
|
|
|
|
*/
|
2018-04-28 22:25:25 +02:00
|
|
|
TypeReference return_type;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines if the method has a variable number of arguments (VarArg)
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_vararg = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing,
|
|
|
|
* but can be overridden by the user to add custom functionality.
|
|
|
|
* e.g.: _ready, _process, etc.
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_virtual = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines if the call should fallback to Godot's object.Call(string, params) in C#.
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool requires_object_call = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
2019-08-09 03:39:45 +02:00
|
|
|
* Determines if the method visibility is 'internal' (visible only to files in the same assembly).
|
2017-10-02 23:24:00 +02:00
|
|
|
* Currently, we only use this for methods that are not meant to be exposed,
|
|
|
|
* but are required by properties as getters or setters.
|
|
|
|
* Methods that are not meant to be exposed are those that begin with underscore and are not virtual.
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_internal = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
List<ArgumentInterface> arguments;
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
const DocData::MethodDoc *method_doc = nullptr;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_deprecated = false;
|
2019-04-25 17:11:01 +02:00
|
|
|
String deprecation_message;
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
void add_argument(const ArgumentInterface &argument) {
|
|
|
|
arguments.push_back(argument);
|
|
|
|
}
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
MethodInterface() {}
|
2017-10-02 23:24:00 +02:00
|
|
|
};
|
|
|
|
|
2020-03-14 19:20:17 +01:00
|
|
|
struct SignalInterface {
|
|
|
|
String name;
|
|
|
|
StringName cname;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Name of the C# method
|
|
|
|
*/
|
|
|
|
String proxy_name;
|
|
|
|
|
|
|
|
List<ArgumentInterface> arguments;
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
const DocData::MethodDoc *method_doc = nullptr;
|
2020-03-14 19:20:17 +01:00
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_deprecated = false;
|
2020-03-14 19:20:17 +01:00
|
|
|
String deprecation_message;
|
|
|
|
|
|
|
|
void add_argument(const ArgumentInterface &argument) {
|
|
|
|
arguments.push_back(argument);
|
|
|
|
}
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
SignalInterface() {}
|
2020-03-14 19:20:17 +01:00
|
|
|
};
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
struct TypeInterface {
|
|
|
|
/**
|
|
|
|
* Identifier name for this type.
|
|
|
|
* Also used to format [c_out].
|
|
|
|
*/
|
|
|
|
String name;
|
2017-12-24 03:17:48 +01:00
|
|
|
StringName cname;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Identifier name of the base class.
|
|
|
|
*/
|
2017-12-24 03:17:48 +01:00
|
|
|
StringName base_name;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Name of the C# class
|
|
|
|
*/
|
|
|
|
String proxy_name;
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
ClassDB::APIType api_type = ClassDB::API_NONE;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_enum = false;
|
|
|
|
bool is_object_type = false;
|
|
|
|
bool is_singleton = false;
|
|
|
|
bool is_reference = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Used only by Object-derived types.
|
2018-08-27 20:39:51 +02:00
|
|
|
* Determines if this type is not abstract (incomplete).
|
2017-10-02 23:24:00 +02:00
|
|
|
* e.g.: CanvasItem cannot be instantiated.
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool is_instantiable = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Used only by Object-derived types.
|
|
|
|
* Determines if the C# class owns the native handle and must free it somehow when disposed.
|
|
|
|
* e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool memory_own = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-11-14 21:48:49 +01:00
|
|
|
/**
|
|
|
|
* This must be set to true for any struct bigger than 32-bits. Those cannot be passed/returned by value
|
|
|
|
* with internal calls, so we must use pointers instead. Returns must be replace with out parameters.
|
|
|
|
* In this case, [c_out] and [cs_out] must have a different format, explained below.
|
|
|
|
* The Mono IL interpreter icall trampolines don't support passing structs bigger than 32-bits by value (at least not on WASM).
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
bool ret_as_byref_arg = false;
|
2019-11-14 21:48:49 +01:00
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
// !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
|
|
|
|
// !! When renaming those fields, make sure to rename their references in the comments
|
|
|
|
|
|
|
|
// --- C INTERFACE ---
|
|
|
|
|
|
|
|
static const char *DEFAULT_VARARG_C_IN;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
|
|
|
|
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
|
|
|
* the name of that local must be specified with [c_arg_in].
|
|
|
|
* For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
|
|
|
|
* Formatting elements:
|
|
|
|
* %0: [c_type] of the parameter
|
|
|
|
* %1: name of the parameter
|
|
|
|
*/
|
|
|
|
String c_in;
|
|
|
|
|
|
|
|
/**
|
2018-10-17 21:37:57 +02:00
|
|
|
* Determines the expression that will be passed as argument to ptrcall.
|
2017-10-02 23:24:00 +02:00
|
|
|
* By default the value equals the name of the parameter,
|
|
|
|
* this varies for types that require special manipulation via [c_in].
|
|
|
|
* Formatting elements:
|
|
|
|
* %0 or %s: name of the parameter
|
|
|
|
*/
|
2020-05-12 17:01:17 +02:00
|
|
|
String c_arg_in = "%s";
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* One or more statements that determine how a variable of this type is returned from a function.
|
|
|
|
* It must contain the return statement(s).
|
|
|
|
* Formatting elements:
|
|
|
|
* %0: [c_type_out] of the return type
|
|
|
|
* %1: name of the variable to be returned
|
|
|
|
* %2: [name] of the return type
|
2019-11-14 21:48:49 +01:00
|
|
|
* ---------------------------------------
|
|
|
|
* If [ret_as_byref_arg] is true, the format is different. Instead of using a return statement,
|
|
|
|
* the value must be assigned to a parameter. This type of this parameter is a pointer to [c_type_out].
|
|
|
|
* Formatting elements:
|
|
|
|
* %0: [c_type_out] of the return type
|
|
|
|
* %1: name of the variable to be returned
|
|
|
|
* %2: [name] of the return type
|
|
|
|
* %3: name of the parameter that must be assigned the return value
|
2017-10-02 23:24:00 +02:00
|
|
|
*/
|
|
|
|
String c_out;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The actual expected type, as seen (in most cases) in Variant copy constructors
|
|
|
|
* Used for the type of the return variable and to format [c_in].
|
|
|
|
* The value must be the following depending of the type:
|
|
|
|
* Object-derived types: Object*
|
|
|
|
* Other types: [name]
|
|
|
|
* -- Exceptions --
|
|
|
|
* VarArg (fictitious type to represent variable arguments): Array
|
|
|
|
* float: double (because ptrcall only supports double)
|
|
|
|
* int: int64_t (because ptrcall only supports int64_t and uint64_t)
|
|
|
|
* Reference types override this for the type of the return variable: Ref<Reference>
|
|
|
|
*/
|
|
|
|
String c_type;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines the type used for parameters in function signatures.
|
|
|
|
*/
|
|
|
|
String c_type_in;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines the return type used for function signatures.
|
|
|
|
* Also used to construct a default value to return in case of errors,
|
|
|
|
* and to format [c_out].
|
|
|
|
*/
|
|
|
|
String c_type_out;
|
|
|
|
|
|
|
|
// --- C# INTERFACE ---
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An expression that overrides the way the parameter is passed to the internal call.
|
|
|
|
* If empty, the parameter is passed as is.
|
|
|
|
* Formatting elements:
|
|
|
|
* %0 or %s: name of the parameter
|
|
|
|
*/
|
|
|
|
String cs_in;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* One or more statements that determine how a variable of this type is returned from a method.
|
|
|
|
* It must contain the return statement(s).
|
|
|
|
* Formatting elements:
|
2019-11-14 21:48:49 +01:00
|
|
|
* %0: internal method name
|
|
|
|
* %1: internal method call arguments without surrounding parenthesis
|
|
|
|
* %2: [cs_type] of the return type
|
|
|
|
* %3: [im_type_out] of the return type
|
2017-10-02 23:24:00 +02:00
|
|
|
*/
|
|
|
|
String cs_out;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type used for method signatures, both for parameters and the return type.
|
2018-08-27 20:39:51 +02:00
|
|
|
* Same as [proxy_name] except for variable arguments (VarArg) and collections (which include the namespace).
|
2017-10-02 23:24:00 +02:00
|
|
|
*/
|
|
|
|
String cs_type;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type used for parameters of internal call methods.
|
|
|
|
*/
|
|
|
|
String im_type_in;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type used for the return type of internal call methods.
|
|
|
|
*/
|
|
|
|
String im_type_out;
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
const DocData::ClassDoc *class_doc = nullptr;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
List<ConstantInterface> constants;
|
|
|
|
List<EnumInterface> enums;
|
|
|
|
List<PropertyInterface> properties;
|
2017-10-02 23:24:00 +02:00
|
|
|
List<MethodInterface> methods;
|
2020-03-14 19:20:17 +01:00
|
|
|
List<SignalInterface> signals_;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
|
2017-10-02 23:24:00 +02:00
|
|
|
for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (E->get().cname == p_cname) {
|
2017-10-02 23:24:00 +02:00
|
|
|
return &E->get();
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-03-18 21:59:35 +01:00
|
|
|
const PropertyInterface *find_property_by_name(const StringName &p_cname) const {
|
|
|
|
for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (E->get().cname == p_cname) {
|
2019-03-18 21:59:35 +01:00
|
|
|
return &E->get();
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2019-03-18 21:59:35 +01:00
|
|
|
}
|
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2019-03-18 21:59:35 +01:00
|
|
|
}
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
|
|
|
|
for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (E->get().proxy_name == p_proxy_name) {
|
2017-12-24 03:17:48 +01:00
|
|
|
return &E->get();
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2017-12-24 03:17:48 +01:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2017-12-24 03:17:48 +01:00
|
|
|
}
|
|
|
|
|
2020-03-14 19:20:17 +01:00
|
|
|
const MethodInterface *find_method_by_proxy_name(const String &p_proxy_name) const {
|
|
|
|
for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (E->get().proxy_name == p_proxy_name) {
|
2020-03-14 19:20:17 +01:00
|
|
|
return &E->get();
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2020-03-14 19:20:17 +01:00
|
|
|
}
|
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2020-03-14 19:20:17 +01:00
|
|
|
}
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
private:
|
|
|
|
static void _init_value_type(TypeInterface &itype) {
|
|
|
|
itype.proxy_name = itype.name;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
itype.c_type = itype.name;
|
|
|
|
itype.cs_type = itype.proxy_name;
|
|
|
|
itype.im_type_in = "ref " + itype.proxy_name;
|
|
|
|
itype.im_type_out = itype.proxy_name;
|
|
|
|
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
|
2017-12-24 03:17:48 +01:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
public:
|
|
|
|
static TypeInterface create_value_type(const String &p_name) {
|
|
|
|
TypeInterface itype;
|
|
|
|
itype.name = p_name;
|
|
|
|
itype.cname = StringName(p_name);
|
|
|
|
_init_value_type(itype);
|
|
|
|
return itype;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypeInterface create_value_type(const StringName &p_name) {
|
|
|
|
TypeInterface itype;
|
|
|
|
itype.name = p_name.operator String();
|
|
|
|
itype.cname = p_name;
|
|
|
|
_init_value_type(itype);
|
2017-10-02 23:24:00 +02:00
|
|
|
return itype;
|
|
|
|
}
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
|
2017-10-02 23:24:00 +02:00
|
|
|
TypeInterface itype;
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
itype.name = p_cname;
|
|
|
|
itype.cname = p_cname;
|
|
|
|
itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name;
|
2017-10-02 23:24:00 +02:00
|
|
|
itype.api_type = p_api_type;
|
|
|
|
itype.is_object_type = true;
|
|
|
|
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
|
|
|
|
|
|
|
|
return itype;
|
|
|
|
}
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
|
|
|
|
r_itype.name = p_cname;
|
|
|
|
r_itype.cname = p_cname;
|
|
|
|
r_itype.proxy_name = r_itype.name;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
r_itype.c_type = r_itype.name;
|
|
|
|
r_itype.c_type_in = "MonoObject*";
|
|
|
|
r_itype.c_type_out = "MonoObject*";
|
|
|
|
r_itype.cs_type = r_itype.proxy_name;
|
|
|
|
r_itype.im_type_in = r_itype.proxy_name;
|
|
|
|
r_itype.im_type_out = r_itype.proxy_name;
|
|
|
|
}
|
|
|
|
|
2018-04-28 22:25:25 +02:00
|
|
|
static void postsetup_enum_type(TypeInterface &r_enum_itype) {
|
2019-04-25 20:24:48 +02:00
|
|
|
// C interface for enums is the same as that of 'uint32_t'. Remember to apply
|
|
|
|
// any of the changes done here to the 'uint32_t' type interface as well.
|
2018-10-17 21:37:57 +02:00
|
|
|
|
|
|
|
r_enum_itype.c_arg_in = "&%s_in";
|
|
|
|
{
|
|
|
|
// The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
|
|
|
|
r_enum_itype.c_in = "\t%0 %1_in = (%0)%1;\n";
|
|
|
|
r_enum_itype.c_out = "\treturn (%0)%1;\n";
|
|
|
|
r_enum_itype.c_type = "int64_t";
|
|
|
|
}
|
|
|
|
r_enum_itype.c_type_in = "int32_t";
|
|
|
|
r_enum_itype.c_type_out = r_enum_itype.c_type_in;
|
|
|
|
|
2018-04-28 22:25:25 +02:00
|
|
|
r_enum_itype.cs_type = r_enum_itype.proxy_name;
|
|
|
|
r_enum_itype.cs_in = "(int)%s";
|
2019-11-14 21:48:49 +01:00
|
|
|
r_enum_itype.cs_out = "return (%2)%0(%1);";
|
2018-04-28 22:25:25 +02:00
|
|
|
r_enum_itype.im_type_in = "int";
|
|
|
|
r_enum_itype.im_type_out = "int";
|
|
|
|
r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name];
|
|
|
|
}
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
TypeInterface() {}
|
2017-10-02 23:24:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct InternalCall {
|
|
|
|
String name;
|
|
|
|
String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
|
|
|
|
String im_sig; // Signature for the C# method declaration
|
|
|
|
String unique_sig; // Unique signature to avoid duplicates in containers
|
2020-11-24 10:12:55 +01:00
|
|
|
bool editor_only = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
InternalCall() {}
|
|
|
|
|
|
|
|
InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
|
|
|
name = p_name;
|
|
|
|
im_type_out = p_im_type_out;
|
|
|
|
im_sig = p_im_sig;
|
|
|
|
unique_sig = p_unique_sig;
|
|
|
|
editor_only = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
|
|
|
name = p_name;
|
|
|
|
im_type_out = p_im_type_out;
|
|
|
|
im_sig = p_im_sig;
|
|
|
|
unique_sig = p_unique_sig;
|
|
|
|
editor_only = api_type == ClassDB::API_EDITOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(const InternalCall &p_a) const {
|
|
|
|
return p_a.unique_sig == unique_sig;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
bool log_print_enabled = true;
|
|
|
|
bool initialized = false;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2018-01-09 19:06:59 +01:00
|
|
|
OrderedHashMap<StringName, TypeInterface> obj_types;
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
Map<StringName, TypeInterface> placeholder_types;
|
|
|
|
Map<StringName, TypeInterface> builtin_types;
|
|
|
|
Map<StringName, TypeInterface> enum_types;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
List<EnumInterface> global_enums;
|
|
|
|
List<ConstantInterface> global_constants;
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
List<InternalCall> method_icalls;
|
|
|
|
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
|
|
|
|
|
2017-10-29 02:37:13 +01:00
|
|
|
List<const InternalCall *> generated_icall_funcs;
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
List<InternalCall> core_custom_icalls;
|
|
|
|
List<InternalCall> editor_custom_icalls;
|
|
|
|
|
2020-03-17 07:33:00 +01:00
|
|
|
Map<StringName, List<StringName>> blacklisted_methods;
|
2019-05-24 00:40:16 +02:00
|
|
|
|
|
|
|
void _initialize_blacklisted_methods();
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
struct NameCache {
|
2020-05-16 04:03:05 +02:00
|
|
|
StringName type_void = StaticCString::create("void");
|
|
|
|
StringName type_Variant = StaticCString::create("Variant");
|
|
|
|
StringName type_VarArg = StaticCString::create("VarArg");
|
|
|
|
StringName type_Object = StaticCString::create("Object");
|
|
|
|
StringName type_Reference = StaticCString::create("Reference");
|
|
|
|
StringName type_RID = StaticCString::create("RID");
|
|
|
|
StringName type_String = StaticCString::create("String");
|
|
|
|
StringName type_StringName = StaticCString::create("StringName");
|
|
|
|
StringName type_NodePath = StaticCString::create("NodePath");
|
|
|
|
StringName type_at_GlobalScope = StaticCString::create("@GlobalScope");
|
|
|
|
StringName enum_Error = StaticCString::create("Error");
|
|
|
|
|
|
|
|
StringName type_sbyte = StaticCString::create("sbyte");
|
|
|
|
StringName type_short = StaticCString::create("short");
|
|
|
|
StringName type_int = StaticCString::create("int");
|
|
|
|
StringName type_byte = StaticCString::create("byte");
|
|
|
|
StringName type_ushort = StaticCString::create("ushort");
|
|
|
|
StringName type_uint = StaticCString::create("uint");
|
|
|
|
StringName type_long = StaticCString::create("long");
|
|
|
|
StringName type_ulong = StaticCString::create("ulong");
|
|
|
|
|
|
|
|
StringName type_bool = StaticCString::create("bool");
|
|
|
|
StringName type_float = StaticCString::create("float");
|
|
|
|
StringName type_double = StaticCString::create("double");
|
|
|
|
|
|
|
|
StringName type_Vector2 = StaticCString::create("Vector2");
|
|
|
|
StringName type_Rect2 = StaticCString::create("Rect2");
|
|
|
|
StringName type_Vector3 = StaticCString::create("Vector3");
|
|
|
|
|
|
|
|
// Object not included as it must be checked for all derived classes
|
|
|
|
static constexpr int nullable_types_count = 17;
|
|
|
|
StringName nullable_types[nullable_types_count] = {
|
|
|
|
type_String,
|
|
|
|
type_StringName,
|
|
|
|
type_NodePath,
|
|
|
|
|
|
|
|
StaticCString::create(_STR(Array)),
|
|
|
|
StaticCString::create(_STR(Dictionary)),
|
|
|
|
StaticCString::create(_STR(Callable)),
|
|
|
|
StaticCString::create(_STR(Signal)),
|
|
|
|
|
|
|
|
StaticCString::create(_STR(PackedByteArray)),
|
|
|
|
StaticCString::create(_STR(PackedInt32Array)),
|
|
|
|
StaticCString::create(_STR(PackedInt64rray)),
|
|
|
|
StaticCString::create(_STR(PackedFloat32Array)),
|
|
|
|
StaticCString::create(_STR(PackedFloat64Array)),
|
|
|
|
StaticCString::create(_STR(PackedStringArray)),
|
|
|
|
StaticCString::create(_STR(PackedVector2Array)),
|
|
|
|
StaticCString::create(_STR(PackedVector3Array)),
|
|
|
|
StaticCString::create(_STR(PackedColorArray)),
|
|
|
|
};
|
|
|
|
|
|
|
|
bool is_nullable_type(const StringName &p_type) const {
|
|
|
|
for (int i = 0; i < nullable_types_count; i++) {
|
|
|
|
if (p_type == nullable_types[i]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-12-24 03:17:48 +01:00
|
|
|
}
|
|
|
|
|
2020-05-16 04:03:05 +02:00
|
|
|
NameCache() {}
|
|
|
|
|
2019-04-25 15:45:12 +02:00
|
|
|
private:
|
2017-12-24 03:17:48 +01:00
|
|
|
NameCache(const NameCache &);
|
|
|
|
NameCache &operator=(const NameCache &);
|
|
|
|
};
|
|
|
|
|
2018-01-01 03:04:49 +01:00
|
|
|
NameCache name_cache;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
|
2017-10-02 23:24:00 +02:00
|
|
|
const List<InternalCall>::Element *it = p_list.front();
|
|
|
|
while (it) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (it->get().name == p_name) {
|
2020-05-10 12:56:01 +02:00
|
|
|
return it;
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
it = it->next();
|
|
|
|
}
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-03-27 20:01:16 +01:00
|
|
|
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
|
|
|
|
for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (E->get().name == p_name) {
|
2019-03-27 20:01:16 +01:00
|
|
|
return &E->get();
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2019-03-27 20:01:16 +01:00
|
|
|
}
|
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
return nullptr;
|
2019-03-27 20:01:16 +01:00
|
|
|
}
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
inline String get_unique_sig(const TypeInterface &p_type) {
|
2020-05-16 04:03:05 +02:00
|
|
|
if (p_type.is_reference) {
|
2017-10-02 23:24:00 +02:00
|
|
|
return "Ref";
|
2020-05-16 04:03:05 +02:00
|
|
|
} else if (p_type.is_object_type) {
|
2017-10-02 23:24:00 +02:00
|
|
|
return "Obj";
|
2020-05-16 04:03:05 +02:00
|
|
|
} else if (p_type.is_enum) {
|
2018-04-28 22:25:25 +02:00
|
|
|
return "int";
|
2020-05-16 04:03:05 +02:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
return p_type.name;
|
|
|
|
}
|
|
|
|
|
2019-03-18 21:59:35 +01:00
|
|
|
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
|
|
|
|
|
2018-10-18 19:41:10 +02:00
|
|
|
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
|
|
|
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
2017-12-24 03:17:48 +01:00
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
void _generate_method_icalls(const TypeInterface &p_itype);
|
|
|
|
|
2018-04-28 22:25:25 +02:00
|
|
|
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
|
|
|
|
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-04-25 20:24:48 +02:00
|
|
|
StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
|
|
|
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
|
|
|
|
2019-09-24 15:09:54 +02:00
|
|
|
bool _arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
|
2020-05-16 04:03:05 +02:00
|
|
|
bool _arg_default_value_is_assignable_to_type(const Variant &p_val, const TypeInterface &p_arg_type);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-09-24 15:09:54 +02:00
|
|
|
bool _populate_object_type_interfaces();
|
2017-10-02 23:24:00 +02:00
|
|
|
void _populate_builtin_type_interfaces();
|
|
|
|
|
2017-12-24 03:17:48 +01:00
|
|
|
void _populate_global_constants();
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
|
|
|
|
|
2019-04-19 01:10:08 +02:00
|
|
|
Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
|
|
|
|
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
|
2020-03-14 19:20:17 +01:00
|
|
|
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
|
2017-10-29 02:37:13 +01:00
|
|
|
|
2021-01-13 11:17:39 +01:00
|
|
|
void _generate_array_extensions(StringBuilder &p_output);
|
2019-04-19 01:10:08 +02:00
|
|
|
void _generate_global_constants(StringBuilder &p_output);
|
2017-12-24 03:17:48 +01:00
|
|
|
|
2019-04-19 01:10:08 +02:00
|
|
|
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, StringBuilder &p_output);
|
2017-10-29 02:37:13 +01:00
|
|
|
|
2019-04-19 01:10:08 +02:00
|
|
|
Error _save_file(const String &p_path, const StringBuilder &p_content);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-04-25 15:45:12 +02:00
|
|
|
void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-04-25 15:45:12 +02:00
|
|
|
void _initialize();
|
2018-01-01 03:04:49 +01:00
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
public:
|
2019-12-28 19:12:32 +01:00
|
|
|
Error generate_cs_core_project(const String &p_proj_dir);
|
|
|
|
Error generate_cs_editor_project(const String &p_proj_dir);
|
2019-04-25 15:45:12 +02:00
|
|
|
Error generate_cs_api(const String &p_output_dir);
|
2017-10-02 23:24:00 +02:00
|
|
|
Error generate_glue(const String &p_output_dir);
|
|
|
|
|
2019-07-03 09:44:53 +02:00
|
|
|
_FORCE_INLINE_ bool is_log_print_enabled() { return log_print_enabled; }
|
|
|
|
_FORCE_INLINE_ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; }
|
2019-04-25 15:45:12 +02:00
|
|
|
|
2019-09-24 15:09:54 +02:00
|
|
|
_FORCE_INLINE_ bool is_initialized() { return initialized; }
|
|
|
|
|
2018-02-22 13:13:51 +01:00
|
|
|
static uint32_t get_version();
|
|
|
|
|
2019-04-25 15:45:12 +02:00
|
|
|
static void handle_cmdline_args(const List<String> &p_cmdline_args);
|
2018-01-01 03:04:49 +01:00
|
|
|
|
2020-05-12 17:01:17 +02:00
|
|
|
BindingsGenerator() {
|
2019-04-25 15:45:12 +02:00
|
|
|
_initialize();
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif // BINDINGS_GENERATOR_H
|