Merge pull request #194 from BastiaanOlij/nativescript-1.1-rebased
Nativescript 1.1 rebasedpull/195/head
commit
d0d18ca704
|
@ -1,8 +1,3 @@
|
|||
# Generated bindings
|
||||
src/*.cpp
|
||||
src/*.hpp
|
||||
include/*.hpp
|
||||
|
||||
# Misc
|
||||
logs/*
|
||||
|
||||
|
@ -16,3 +11,8 @@ logs/*
|
|||
*.pdb
|
||||
*.lib
|
||||
bin
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.user
|
||||
*.files
|
||||
*.includes
|
||||
|
|
187
README.md
187
README.md
|
@ -1,123 +1,180 @@
|
|||
# godot-cpp
|
||||
C++ bindings for the Godot script API
|
||||
|
||||
# Creating a GDNative library (Linux)
|
||||
Create a directory named `SimpleLibrary` with subdirectories `lib, src`
|
||||
Note that the master branch in this repository is for use with Godot build from its latest master.
|
||||
If you need to support older versions of Godot use the relevant branch for that version in this repository.
|
||||
|
||||
The instructions below feature the new NativeScript 1.1 class structure and will only work for modules created for Godot 3.1 and later.
|
||||
|
||||
- [**Getting Started**](#getting-started)
|
||||
- [**Creating a simple class**](#creating-a-simple-class)
|
||||
|
||||
## Getting Started
|
||||
|
||||
| **Build latest version of Godot** | [**GitHub**](https://github.com/godotengine/godot) | [**Docs**](https://godot.readthedocs.io/en/latest/development/compiling/index.html) |
|
||||
| --- | --- | --- |
|
||||
|
||||
### Setting up a new project
|
||||
|
||||
We recommend using git for managing your project and the instructions below assume so. Alternatively you can download the source code directly from GitHub in which case you need to download both [godot-cpp](https://github.com/GodotNativeTools/godot-cpp) and [godot_headers](https://github.com/GodotNativeTools/godot_headers).
|
||||
|
||||
Getting latest `godot-cpp` and `godot_headers`
|
||||
```
|
||||
$ git clone https://github.com/GodotNativeTools/godot-cpp
|
||||
$ git clone https://github.com/GodotNativeTools/godot_headers
|
||||
```
|
||||
right now our directory structure should look like this:
|
||||
```
|
||||
godot-cpp
|
||||
godot_headers
|
||||
SimpleLibrary
|
||||
├── lib/
|
||||
└── src/
|
||||
$ mkdir SimpleLibrary
|
||||
$ cd SimpleLibrary
|
||||
$ mkdir bin
|
||||
$ mkdir src
|
||||
$ git clone --recursive https://github.com/GodotNativeTools/godot-cpp
|
||||
```
|
||||
|
||||
Now to generate cpp bindings
|
||||
Note that if you wish to use a specific branch, add the -b option to the clone command:
|
||||
```
|
||||
$ git clone --recursive https://github.com/GodotNativeTools/godot-cpp -b 3.0
|
||||
```
|
||||
|
||||
Right now our directory structure should look like this:
|
||||
```
|
||||
SimpleLibrary/
|
||||
├─godot-cpp/
|
||||
| └─godot_headers/
|
||||
├─bin/
|
||||
└─src/
|
||||
```
|
||||
|
||||
### Updating the api.json
|
||||
Our api.json file contains meta data of all the classes that are part of the Godot core and are needed to generate the C++ binding classes for use in GDNative modules.
|
||||
|
||||
A file is supplied in our repository for your convinience but if you are running a custom build of Godot and need access to classes that have recent changes a new api.json file must be generated. You do this by starting your Godot executable with the following parameters:
|
||||
|
||||
```
|
||||
$ godot --gdnative-generate-json-api api.json
|
||||
```
|
||||
|
||||
Now copy the api.json file into your folder structure so its easy to access.
|
||||
|
||||
### Compiling the cpp bindings library
|
||||
The final step is to compile our cpp bindings library:
|
||||
```
|
||||
$ cd godot-cpp
|
||||
$ scons godotbinpath="../godot_fork/bin/godot_binary" p=linux
|
||||
$ scons platform=<your platform> generate_bindings=yes
|
||||
$ cd ..
|
||||
```
|
||||
resulting libraries will be placed under `bin/` and the generated headers will be placed under `include/*`
|
||||
|
||||
**Note:**
|
||||
> `generate_bindings=yes` is used to force regenerating C++ bindings (`godot_api.json` - Godot API)
|
||||
> Replace `<your platform>` with either `windows`, `linux` or `osx`.
|
||||
|
||||
> Include `use_llvm=yes` for using clang++
|
||||
|
||||
> You may need to specify `headers=../godot_headers` if you have compilation issues related to missing include files
|
||||
> Include `target=runtime` to build a runtime build (windows only at the moment)
|
||||
|
||||
And our directory structure will be
|
||||
```
|
||||
godot-cpp
|
||||
└── bin/libgodot-cpp.a
|
||||
godot_headers
|
||||
SimpleLibrary
|
||||
├── lib/
|
||||
└── src/
|
||||
```
|
||||
> The resulting library will be created in `godot-cpp/bin/`, take note of its name as it will be different depending on platform.
|
||||
|
||||
# Creating simple class
|
||||
> If you want to use an alternative api.json file add `use_custom_api_file=yes custom_api_file=../api.json`, be sure to specify the correct location of where you placed your file.
|
||||
|
||||
## Creating a simple class
|
||||
|
||||
Create `init.cpp` under `SimpleLibrary/src/` and add the following code
|
||||
```cpp
|
||||
#include <core/Godot.hpp>
|
||||
#include <Godot.hpp>
|
||||
#include <Reference.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
class SimpleClass : public GodotScript<Reference> {
|
||||
GODOT_CLASS(SimpleClass);
|
||||
class SimpleClass : public Reference {
|
||||
GODOT_CLASS(SimpleClass, Reference);
|
||||
public:
|
||||
SimpleClass() { }
|
||||
SimpleClass() { }
|
||||
|
||||
void test_void_method() {
|
||||
Godot::print("This is test");
|
||||
}
|
||||
/* _init must exist as it is called by Godot */
|
||||
void _init() { }
|
||||
|
||||
Variant method(Variant arg) {
|
||||
Variant ret;
|
||||
ret = arg;
|
||||
void test_void_method() {
|
||||
Godot::print("This is test");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Variant method(Variant arg) {
|
||||
Variant ret;
|
||||
ret = arg;
|
||||
|
||||
static void _register_methods() {
|
||||
register_method("method", &SimpleClass::method);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* How to register exports like gdscript
|
||||
* export var _name = "SimpleClass"
|
||||
**/
|
||||
register_property((char *)"base/name", &SimpleClass::_name, String("SimpleClass"));
|
||||
static void _register_methods() {
|
||||
register_method("method", &SimpleClass::method);
|
||||
|
||||
/** For registering signal **/
|
||||
// register_signal<SimpleClass>("signal_name");
|
||||
// register_signal<SimpleClass>("signal_name", "string_argument", GODOT_VARIANT_TYPE_STRING)
|
||||
}
|
||||
/**
|
||||
* How to register exports like gdscript
|
||||
* export var _name = "SimpleClass"
|
||||
**/
|
||||
register_property<SimpleClass, String>("base/name", &SimpleClass::_name, String("SimpleClass"));
|
||||
|
||||
String _name;
|
||||
/* or alternatively with getter and setter methods */
|
||||
register_property<SimpleClass, int>("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0);
|
||||
|
||||
/** For registering signal **/
|
||||
// register_signal<SimpleClass>("signal_name");
|
||||
// register_signal<SimpleClass>("signal_name", "string_argument", GODOT_VARIANT_TYPE_STRING)
|
||||
}
|
||||
|
||||
String _name;
|
||||
int _value;
|
||||
|
||||
void set_value(int p_value) {
|
||||
_value = p_value;
|
||||
}
|
||||
|
||||
int get_value() const {
|
||||
return _value;
|
||||
}
|
||||
};
|
||||
|
||||
/** GDNative Initialize **/
|
||||
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o)
|
||||
{
|
||||
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
||||
godot::Godot::gdnative_init(o);
|
||||
}
|
||||
|
||||
/** GDNative Terminate **/
|
||||
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o)
|
||||
{
|
||||
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
|
||||
godot::Godot::gdnative_terminate(o);
|
||||
}
|
||||
|
||||
/** NativeScript Initialize **/
|
||||
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle)
|
||||
{
|
||||
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
||||
godot::Godot::nativescript_init(handle);
|
||||
|
||||
godot::register_class<SimpleClass>();
|
||||
}
|
||||
```
|
||||
|
||||
# Compiling
|
||||
### Compiling
|
||||
|
||||
*Linux*
|
||||
```
|
||||
$ cd SimpleLibrary
|
||||
$ clang -fPIC -o src/init.os -c src/init.cpp -g -O3 -std=c++14 -I../godot-cpp/include -Igodot_headers
|
||||
$ clang -o lib/libtest.so -shared src/init.os -L../godot-cpp/lib -lgodot-cpp
|
||||
$ clang -fPIC -o src/init.os -c src/init.cpp -g -O3 -std=c++14 -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igodot-cpp/godot_headers
|
||||
$ clang -o bin/libtest.so -shared src/init.os -Lgodot-cpp/bin -l<name of the godot-cpp>
|
||||
```
|
||||
This creates the file `libtest.so` in your `SimpleLibrary/lib` directory. For windows you need to find out what compiler flags need to be used.
|
||||
> This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
|
||||
|
||||
# Creating `.gdns` file
|
||||
> You will need to replace `<name of the godot-cpp>` with the file that was created in [**Compiling the cpp bindings library**](#compiling-the-cpp-bindings-library)
|
||||
|
||||
*Windows*
|
||||
```
|
||||
$ cd SimpleLibrary
|
||||
$ cl /Fosrc/init.obj /c src/init.cpp /nologo -EHsc -DNDEBUG /MDd /Igodot-cpp\include /Igodot-cpp\include\core /Igodot-cpp\include\gen /Igodot-cpp\godot_headers
|
||||
$ link /nologo /dll /out:bin\libtest.dll /implib:bin\libsimple.lib src\init.obj godot-cpp\bin\<name of the godot-cpp>
|
||||
```
|
||||
> This creates the file `libtest.dll` in your `SimpleLibrary/bin` directory.
|
||||
|
||||
> You will need to replace `<name of the godot-cpp>` with the file that was created in [**Compiling the cpp bindings library**](#compiling-the-cpp-bindings-library)
|
||||
|
||||
> Finally replace `/MDd` with `/MD` if you're generated a runtime build.
|
||||
|
||||
*macOS*
|
||||
For OSX you need to find out what compiler flags need to be used.
|
||||
|
||||
### Creating `.gdnlib` and `.gdns` files
|
||||
follow [godot_header/README.md](https://github.com/GodotNativeTools/godot_headers/blob/master/README.md#how-do-i-use-native-scripts-from-the-editor) to create the `.gdns`
|
||||
|
||||
# Implementing with gdscript
|
||||
### Implementing with gdscript
|
||||
```gdscript
|
||||
var simpleclass = load("res://simpleclass.gdns").new();
|
||||
simpleclass.method("Test argument");
|
||||
|
|
11
SConstruct
11
SConstruct
|
@ -96,7 +96,10 @@ elif env['platform'] == 'windows':
|
|||
env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++'])
|
||||
|
||||
|
||||
env.Append(CPPPATH=['.', env['headers_dir'], 'include', 'include/core'])
|
||||
env.Append(CPPPATH=['.', env['headers_dir'], 'include', 'include/gen', 'include/core'])
|
||||
|
||||
# Generate bindings?
|
||||
json_api_file = ''
|
||||
|
||||
# Generate bindings?
|
||||
json_api_file = ''
|
||||
|
@ -104,7 +107,7 @@ json_api_file = ''
|
|||
if ARGUMENTS.get('use_custom_api_file', 'no') == 'yes':
|
||||
json_api_file = ARGUMENTS.get('custom_api_file', '')
|
||||
else:
|
||||
json_api_file = os.path.join(os.getcwd(), 'godot_api.json')
|
||||
json_api_file = os.path.join(os.getcwd(), 'godot_headers', 'api.json')
|
||||
|
||||
if ARGUMENTS.get('generate_bindings', 'no') == 'yes':
|
||||
# Actually create the bindings here
|
||||
|
@ -113,9 +116,11 @@ if ARGUMENTS.get('generate_bindings', 'no') == 'yes':
|
|||
|
||||
binding_generator.generate_bindings(json_api_file)
|
||||
|
||||
|
||||
# source to compile
|
||||
sources = []
|
||||
add_sources(sources, 'src/core', 'cpp')
|
||||
add_sources(sources, 'src', 'cpp')
|
||||
add_sources(sources, 'src/gen', 'cpp')
|
||||
|
||||
library = env.StaticLibrary(
|
||||
target='bin/' + 'libgodot-cpp.{}.{}.{}'.format(env['platform'], env['target'], env['bits']), source=sources
|
||||
|
|
|
@ -21,19 +21,22 @@ def generate_bindings(path):
|
|||
|
||||
impl = generate_class_implementation(icalls, used_classes, c)
|
||||
|
||||
header_file = open("include/" + strip_name(c["name"]) + ".hpp", "w+")
|
||||
header_file = open("include/gen/" + strip_name(c["name"]) + ".hpp", "w+")
|
||||
header_file.write(header)
|
||||
|
||||
source_file = open("src/" + strip_name(c["name"]) + ".cpp", "w+")
|
||||
source_file = open("src/gen/" + strip_name(c["name"]) + ".cpp", "w+")
|
||||
source_file.write(impl)
|
||||
|
||||
|
||||
icall_header_file = open("src/__icalls.hpp", "w+")
|
||||
icall_header_file = open("src/gen/__icalls.hpp", "w+")
|
||||
icall_header_file.write(generate_icall_header(icalls))
|
||||
|
||||
icall_source_file = open("src/__icalls.cpp", "w+")
|
||||
icall_source_file = open("src/gen/__icalls.cpp", "w+")
|
||||
icall_source_file.write(generate_icall_implementation(icalls))
|
||||
|
||||
register_types_file = open("src/gen/__register_types.cpp", "w+")
|
||||
register_types_file.write(generate_type_registry(classes))
|
||||
|
||||
|
||||
def is_reference_type(t):
|
||||
for c in classes:
|
||||
|
@ -79,6 +82,8 @@ def generate_class_header(used_classes, c):
|
|||
# so don't include it here because it's not needed
|
||||
if class_name != "Object" and class_name != "Reference":
|
||||
source.append("#include <core/Ref.hpp>")
|
||||
else:
|
||||
source.append("#include <core/TagDB.hpp>")
|
||||
|
||||
|
||||
included = []
|
||||
|
@ -101,7 +106,6 @@ def generate_class_header(used_classes, c):
|
|||
source.append("#include \"" + strip_name(c["base_class"]) + ".hpp\"")
|
||||
|
||||
|
||||
|
||||
source.append("namespace godot {")
|
||||
source.append("")
|
||||
|
||||
|
@ -118,15 +122,40 @@ def generate_class_header(used_classes, c):
|
|||
vararg_templates = ""
|
||||
|
||||
# generate the class definition here
|
||||
source.append("class " + class_name + ("" if c["base_class"] == "" else (" : public " + strip_name(c["base_class"])) ) + " {")
|
||||
source.append("class " + class_name + (" : public _Wrapped" if c["base_class"] == "" else (" : public " + strip_name(c["base_class"])) ) + " {")
|
||||
|
||||
if c["base_class"] == "":
|
||||
source.append("public: enum { ___CLASS_IS_SCRIPT = 0, };")
|
||||
source.append("private:")
|
||||
source.append("")
|
||||
|
||||
if c["singleton"]:
|
||||
source.append("\tstatic " + class_name + " *_singleton;")
|
||||
source.append("")
|
||||
source.append("\t" + class_name + "();")
|
||||
source.append("")
|
||||
|
||||
|
||||
source.append("public:")
|
||||
source.append("")
|
||||
|
||||
# ___get_class_name
|
||||
source.append("\tstatic inline char *___get_class_name() { return (char *) \"" + strip_name(c["name"]) + "\"; }")
|
||||
|
||||
source.append("\tstatic inline Object *___get_from_variant(Variant a) { return (Object *) a; }")
|
||||
if c["singleton"]:
|
||||
source.append("\tstatic inline " + class_name + " *get_singleton()")
|
||||
source.append("\t{")
|
||||
source.append("\t\tif (!" + class_name + "::_singleton) {")
|
||||
source.append("\t\t\t" + class_name + "::_singleton = new " + class_name + ";")
|
||||
source.append("\t\t}")
|
||||
source.append("\t\treturn " + class_name + "::_singleton;")
|
||||
source.append("\t}")
|
||||
source.append("")
|
||||
|
||||
# godot::api->godot_global_get_singleton((char *) \"" + strip_name(c["name"]) + "\");"
|
||||
|
||||
# ___get_class_name
|
||||
source.append("\tstatic inline const char *___get_class_name() { return (const char *) \"" + strip_name(c["name"]) + "\"; }")
|
||||
|
||||
source.append("\tstatic inline Object *___get_from_variant(Variant a) { godot_object *o = (godot_object*) a; return (Object *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, o); }")
|
||||
|
||||
enum_values = []
|
||||
|
||||
|
@ -146,17 +175,26 @@ def generate_class_header(used_classes, c):
|
|||
|
||||
|
||||
if c["instanciable"]:
|
||||
source.append("\tstatic void *operator new(size_t);")
|
||||
|
||||
source.append("\tstatic void operator delete(void *);")
|
||||
source.append("")
|
||||
source.append("")
|
||||
source.append("\tstatic " + class_name + " *_new();")
|
||||
|
||||
source.append("\n\t// methods")
|
||||
|
||||
|
||||
if class_name == "Object":
|
||||
source.append("#ifndef GODOT_CPP_NO_OBJECT_CAST")
|
||||
source.append("\ttemplate<class T>")
|
||||
source.append("\tstatic T *cast_to(const Object *obj);")
|
||||
source.append("#endif")
|
||||
source.append("")
|
||||
|
||||
for method in c["methods"]:
|
||||
|
||||
method_signature = ""
|
||||
|
||||
method_signature += "static " if c["singleton"] else ""
|
||||
# TODO decide what to do about virtual methods
|
||||
# method_signature += "virtual " if method["is_virtual"] else ""
|
||||
method_signature += make_gdnative_type(method["return_type"])
|
||||
method_name = escape_cpp(method["name"])
|
||||
method_signature += method_name + "("
|
||||
|
@ -224,7 +262,7 @@ def generate_class_header(used_classes, c):
|
|||
vararg_templates += "\ttemplate <class... Args> " + method_signature + "Args... args){\n\t\treturn " + method_name + "(" + method_arguments + "Array::make(args...));\n\t}\n"""
|
||||
method_signature += "const Array& __var_args = Array()"
|
||||
|
||||
method_signature += ")" + (" const" if method["is_const"] and not c["singleton"] else "")
|
||||
method_signature += ")" + (" const" if method["is_const"] else "")
|
||||
|
||||
|
||||
source.append("\t" + method_signature + ";")
|
||||
|
@ -234,11 +272,10 @@ def generate_class_header(used_classes, c):
|
|||
source.append("")
|
||||
|
||||
|
||||
|
||||
source.append("}")
|
||||
source.append("")
|
||||
|
||||
|
||||
|
||||
source.append("#endif")
|
||||
|
||||
|
||||
|
@ -279,23 +316,20 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
source.append("namespace godot {")
|
||||
|
||||
|
||||
core_object_name = ("___static_object_" + strip_name(c["name"])) if c["singleton"] else "this"
|
||||
core_object_name = "this"
|
||||
|
||||
|
||||
source.append("")
|
||||
source.append("")
|
||||
|
||||
if c["singleton"]:
|
||||
source.append("static godot_object *" + core_object_name + ";")
|
||||
source.append("" + class_name + " *" + class_name + "::_singleton = NULL;")
|
||||
source.append("")
|
||||
source.append("")
|
||||
|
||||
# FIXME Test if inlining has a huge impact on binary size
|
||||
source.append("static inline void ___singleton_init()")
|
||||
source.append("{")
|
||||
source.append("\tif (" + core_object_name + " == nullptr) {")
|
||||
source.append("\t\t" + core_object_name + " = godot::api->godot_global_get_singleton((char *) \"" + strip_name(c["name"]) + "\");")
|
||||
source.append("\t}")
|
||||
source.append(class_name + "::" + class_name + "() {")
|
||||
source.append("\t_owner = godot::api->godot_global_get_singleton((char *) \"" + strip_name(c["name"]) + "\");")
|
||||
source.append("}")
|
||||
|
||||
source.append("")
|
||||
|
@ -304,19 +338,15 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
|
||||
|
||||
if c["instanciable"]:
|
||||
source.append("void *" + strip_name(c["name"]) + "::operator new(size_t)")
|
||||
source.append(class_name + " *" + strip_name(c["name"]) + "::_new()")
|
||||
source.append("{")
|
||||
source.append("\treturn godot::api->godot_get_class_constructor((char *)\"" + c["name"] + "\")();")
|
||||
source.append("}")
|
||||
|
||||
source.append("void " + strip_name(c["name"]) + "::operator delete(void *ptr)")
|
||||
source.append("{")
|
||||
source.append("\tgodot::api->godot_object_destroy((godot_object *)ptr);")
|
||||
source.append("\treturn (" + class_name + " *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, godot::api->godot_get_class_constructor((char *)\"" + c["name"] + "\")());")
|
||||
source.append("}")
|
||||
|
||||
for method in c["methods"]:
|
||||
method_signature = ""
|
||||
|
||||
|
||||
method_signature += make_gdnative_type(method["return_type"])
|
||||
method_signature += strip_name(c["name"]) + "::" + escape_cpp(method["name"]) + "("
|
||||
|
||||
|
@ -332,20 +362,23 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
method_signature += ", "
|
||||
method_signature += "const Array& __var_args"
|
||||
|
||||
method_signature += ")" + (" const" if method["is_const"] and not c["singleton"] else "")
|
||||
method_signature += ")" + (" const" if method["is_const"] else "")
|
||||
|
||||
source.append(method_signature + " {")
|
||||
|
||||
|
||||
if method["name"] == "free":
|
||||
# dirty hack because Object::free is marked virtual but doesn't actually exist...
|
||||
source.append("\tgodot::api->godot_object_destroy(_owner);")
|
||||
source.append("}")
|
||||
source.append("")
|
||||
continue
|
||||
else:
|
||||
|
||||
if c["singleton"]:
|
||||
source.append("\t___singleton_init();")
|
||||
|
||||
|
||||
source.append("\tstatic godot_method_bind *mb = nullptr;")
|
||||
source.append("\tif (mb == nullptr) {")
|
||||
source.append("\t\tmb = godot::api->godot_method_bind_get_method(\"" + c["name"] +"\", \"" + method["name"] + "\");")
|
||||
source.append("\t}")
|
||||
source.append("\tstatic godot_method_bind *mb = nullptr;")
|
||||
source.append("\tif (mb == nullptr) {")
|
||||
source.append("\t\tmb = godot::api->godot_method_bind_get_method(\"" + c["name"] +"\", \"" + method["name"] + "\");")
|
||||
source.append("\t}")
|
||||
|
||||
return_statement = ""
|
||||
|
||||
|
@ -408,10 +441,17 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
source.append("")
|
||||
|
||||
source.append("\tVariant __result;")
|
||||
source.append("\t*(godot_variant *) &__result = godot::api->godot_method_bind_call(mb, (godot_object *) " + core_object_name + ", (const godot_variant **) __args, " + size + ", nullptr);")
|
||||
source.append("\t*(godot_variant *) &__result = godot::api->godot_method_bind_call(mb, ((const Object *) " + core_object_name + ")->_owner, (const godot_variant **) __args, " + size + ", nullptr);")
|
||||
|
||||
source.append("")
|
||||
|
||||
if is_class_type(method["return_type"]):
|
||||
source.append("\tObject *obj = Object::___get_from_variant(__result);")
|
||||
source.append("\tif (obj->has_method(\"reference\"))")
|
||||
source.append("\t\tobj->callv(\"reference\", Array());")
|
||||
|
||||
source.append("")
|
||||
|
||||
|
||||
for i, argument in enumerate(method["arguments"]):
|
||||
source.append("\tgodot::api->godot_variant_destroy((godot_variant *) &__given_args[" + str(i) + "]);")
|
||||
|
@ -424,7 +464,7 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
if is_reference_type(method["return_type"]):
|
||||
cast += "Ref<" + strip_name(method["return_type"]) + ">::__internal_constructor(__result);"
|
||||
else:
|
||||
cast += "(" + strip_name(method["return_type"]) + " *) (Object *) __result;"
|
||||
cast += "(" + strip_name(method["return_type"]) + " *) " + strip_name(method["return_type"] + "::___get_from_variant(") + "__result);"
|
||||
else:
|
||||
cast += "__result;"
|
||||
source.append("\treturn " + cast)
|
||||
|
@ -445,7 +485,7 @@ def generate_class_implementation(icalls, used_classes, c):
|
|||
|
||||
icall_name = get_icall_name(icall_sig)
|
||||
|
||||
return_statement += icall_name + "(mb, (godot_object *) " + core_object_name
|
||||
return_statement += icall_name + "(mb, (const Object *) " + core_object_name
|
||||
|
||||
for arg in method["arguments"]:
|
||||
return_statement += ", " + escape_cpp(arg["name"]) + (".ptr()" if is_reference_type(arg["type"]) else "")
|
||||
|
@ -494,7 +534,7 @@ def generate_icall_header(icalls):
|
|||
|
||||
method_signature = ""
|
||||
|
||||
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, godot_object *inst"
|
||||
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
|
||||
|
||||
for arg in args:
|
||||
method_signature += ", const "
|
||||
|
@ -547,7 +587,7 @@ def generate_icall_implementation(icalls):
|
|||
|
||||
method_signature = ""
|
||||
|
||||
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, godot_object *inst"
|
||||
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
|
||||
|
||||
for i, arg in enumerate(args):
|
||||
method_signature += ", const "
|
||||
|
@ -568,7 +608,7 @@ def generate_icall_implementation(icalls):
|
|||
source.append(method_signature + " {")
|
||||
|
||||
if ret_type != "void":
|
||||
source.append("\t" + return_type(ret_type) + "ret;")
|
||||
source.append("\t" + ("godot_object *" if is_class_type(ret_type) else return_type(ret_type)) + "ret;")
|
||||
if is_class_type(ret_type):
|
||||
source.append("\tret = nullptr;")
|
||||
|
||||
|
@ -581,7 +621,7 @@ def generate_icall_implementation(icalls):
|
|||
if is_primitive(arg) or is_core_type(arg):
|
||||
wrapped_argument += "(void *) &arg" + str(i)
|
||||
else:
|
||||
wrapped_argument += "(void *) arg" + str(i)
|
||||
wrapped_argument += "(void *) arg" + str(i) + "->_owner"
|
||||
|
||||
wrapped_argument += ","
|
||||
source.append(wrapped_argument)
|
||||
|
@ -589,10 +629,17 @@ def generate_icall_implementation(icalls):
|
|||
source.append("\t};")
|
||||
source.append("")
|
||||
|
||||
source.append("\tgodot::api->godot_method_bind_ptrcall(mb, inst, args, " + ("nullptr" if ret_type == "void" else "&ret") + ");")
|
||||
source.append("\tgodot::api->godot_method_bind_ptrcall(mb, inst->_owner, args, " + ("nullptr" if ret_type == "void" else "&ret") + ");")
|
||||
|
||||
if ret_type != "void":
|
||||
source.append("\treturn ret;")
|
||||
if is_class_type(ret_type):
|
||||
source.append("\tif (ret) {")
|
||||
source.append("\t\treturn (Object *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, ret);")
|
||||
source.append("\t}")
|
||||
source.append("")
|
||||
source.append("\treturn (Object *) ret;")
|
||||
else:
|
||||
source.append("\treturn ret;")
|
||||
|
||||
source.append("}")
|
||||
|
||||
|
@ -604,8 +651,44 @@ def generate_icall_implementation(icalls):
|
|||
|
||||
|
||||
|
||||
def generate_type_registry(classes):
|
||||
source = []
|
||||
|
||||
source.append("#include \"TagDB.hpp\"")
|
||||
source.append("#include <typeinfo>")
|
||||
source.append("\n")
|
||||
|
||||
for c in classes:
|
||||
source.append("#include <" + strip_name(c["name"]) + ".hpp>")
|
||||
|
||||
source.append("")
|
||||
source.append("")
|
||||
|
||||
source.append("namespace godot {")
|
||||
|
||||
source.append("void ___register_types()")
|
||||
source.append("{")
|
||||
|
||||
for c in classes:
|
||||
class_name = strip_name(c["name"])
|
||||
base_class_name = strip_name(c["base_class"])
|
||||
|
||||
class_type_hash = "typeid(" + class_name + ").hash_code()"
|
||||
|
||||
base_class_type_hash = "typeid(" + base_class_name + ").hash_code()"
|
||||
|
||||
if base_class_name == "":
|
||||
base_class_type_hash = "0"
|
||||
|
||||
source.append("\tgodot::_TagDB::register_global_type(\"" + class_name + "\", " + class_type_hash + ", " + base_class_type_hash + ");")
|
||||
|
||||
source.append("}")
|
||||
|
||||
source.append("")
|
||||
source.append("}")
|
||||
|
||||
|
||||
return "\n".join(source)
|
||||
|
||||
|
||||
|
||||
|
@ -664,6 +747,8 @@ def get_used_classes(c):
|
|||
|
||||
|
||||
def strip_name(name):
|
||||
if len(name) == 0:
|
||||
return name
|
||||
if name[0] == '_':
|
||||
return name[1:]
|
||||
return name
|
||||
|
|
140717
godot_api.json
140717
godot_api.json
File diff suppressed because it is too large
Load Diff
|
@ -1 +1 @@
|
|||
Subproject commit 2d221de20c7ddc297b8bb14f0dbd55c053eb3024
|
||||
Subproject commit a51d905c5a34a441c1d4701b57c9de6548efbea3
|
|
@ -21,5 +21,7 @@
|
|||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include "Wrapped.hpp"
|
||||
|
||||
|
||||
#endif // CORETYPES_H
|
||||
|
|
|
@ -107,32 +107,45 @@ typedef float real_t;
|
|||
#define _PLANE_EQ_DOT_EPSILON 0.999
|
||||
#define _PLANE_EQ_D_EPSILON 0.0001
|
||||
|
||||
|
||||
#ifndef ERR_FAIL_COND_V
|
||||
#define ERR_FAIL_COND_V(cond, ret) do { if (cond) { return ret; } } while(0)
|
||||
// ERR/WARN macros
|
||||
#ifndef WARN_PRINT
|
||||
#define WARN_PRINT(msg) fprintf(stdout, "ERROR: %s\n", msg); fflush(stdout)
|
||||
#endif
|
||||
|
||||
#ifndef WARN_PRINTS
|
||||
#define WARN_PRINTS(msg) WARN_PRINT((msg).utf8().get_data())
|
||||
#endif
|
||||
|
||||
#ifndef ERR_PRINT
|
||||
#define ERR_PRINT(x) fprintf(stderr, "ERROR: %s\n", x)
|
||||
#endif
|
||||
|
||||
#ifndef ERR_PRINTS
|
||||
#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL
|
||||
#define ERR_FAIL() ERR_PRINT("Failed")
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL_V
|
||||
#define ERR_FAIL_V(a) return a
|
||||
#define ERR_FAIL_V(a) { ERR_FAIL(); return a; }
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL_COND
|
||||
#define ERR_FAIL_COND(a) do { if (a) { ERR_PRINT(#a); return; } } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL_COND_V
|
||||
#define ERR_FAIL_COND_V(cond, ret) do { if (cond) { ERR_PRINT(#cond); return ret; } } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL_INDEX
|
||||
#define ERR_FAIL_INDEX(a, b)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ERR_PRINT
|
||||
#define ERR_PRINT(msg) fprintf(stderr, "ERROR: %S\n", (msg).unicode_str())
|
||||
#define ERR_FAIL_INDEX(a, b) do { if (a < 0 || a >= b) { ERR_FAIL(); return; } } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef ERR_FAIL_INDEX_V
|
||||
#define ERR_FAIL_INDEX_V(a, b, c)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ERR_FAIL_COND
|
||||
#define ERR_FAIL_COND(a) do { if (a) { fprintf(stderr, #a); return; } } while(0)
|
||||
#define ERR_FAIL_INDEX_V(a, b, c) do { if (a < 0 || a >= b) { ERR_FAIL(); return c; } } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -6,60 +6,52 @@
|
|||
|
||||
#include <gdnative_api_struct.gen.h>
|
||||
#include <nativescript/godot_nativescript.h>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#include "CoreTypes.hpp"
|
||||
#include "Variant.hpp"
|
||||
#include "Ref.hpp"
|
||||
#include "TagDB.hpp"
|
||||
|
||||
#include "Object.hpp"
|
||||
|
||||
#include "GodotGlobal.hpp"
|
||||
|
||||
#include <NativeScript.hpp>
|
||||
#include <GDNativeLibrary.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
|
||||
template<class T>
|
||||
T *as(Object *obj)
|
||||
T *as(const Object *obj)
|
||||
{
|
||||
return (T *) godot::nativescript_api->godot_nativescript_get_userdata(obj);
|
||||
return (T *) godot::nativescript_api->godot_nativescript_get_userdata(obj->_owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *get_wrapper(godot_object *obj)
|
||||
{
|
||||
return (T *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, obj);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
class GodotScript {
|
||||
public:
|
||||
T *owner;
|
||||
|
||||
// GodotScript() {}
|
||||
|
||||
void _init() {}
|
||||
static const char *___get_base_type_name()
|
||||
{
|
||||
return T::___get_class_name();
|
||||
}
|
||||
|
||||
static GodotScript<T> *___get_from_variant(Variant a)
|
||||
{
|
||||
return as<GodotScript<T> >((Object *) a);
|
||||
}
|
||||
|
||||
static void _register_methods() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define GODOT_CLASS(Name) \
|
||||
#define GODOT_CLASS(Name, Base) \
|
||||
public: inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
|
||||
enum { ___CLASS_IS_SCRIPT = 1, }; \
|
||||
inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *) godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as<Name>(script->new_()); return instance; } \
|
||||
inline static const char *___get_base_type_name() { return Base::___get_class_name(); } \
|
||||
inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *) godot::as<Name>(godot::Object::___get_from_variant(a)); } \
|
||||
private:
|
||||
|
||||
#define GODOT_SUBCLASS(Name, Base) \
|
||||
public: inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
|
||||
inline static const char *___get_base_type_name() { return static_cast<const char *>(#Base); } \
|
||||
enum { ___CLASS_IS_SCRIPT = 1, }; \
|
||||
inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *) godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as<Name>(script->new_()); return instance; } \
|
||||
inline static const char *___get_base_type_name() { return #Base; } \
|
||||
inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *) godot::as<Name>(godot::Object::___get_from_variant(a)); } \
|
||||
private:
|
||||
|
||||
|
||||
template<class T>
|
||||
struct _ArgCast {
|
||||
static T _arg_cast(Variant a)
|
||||
|
@ -94,7 +86,8 @@ template<class T>
|
|||
void *_godot_class_instance_func(godot_object *p, void *method_data)
|
||||
{
|
||||
T *d = new T();
|
||||
*(godot_object **) &d->owner = p;
|
||||
d->_owner = p;
|
||||
d->_type_tag = typeid(T).hash_code();
|
||||
d->_init();
|
||||
return d;
|
||||
}
|
||||
|
@ -116,8 +109,10 @@ void register_class()
|
|||
godot_instance_destroy_func destroy = {};
|
||||
destroy.destroy_func = _godot_class_destroy_func<T>;
|
||||
|
||||
_TagDB::register_type(typeid(T).hash_code(), typeid(T).hash_code());
|
||||
|
||||
godot::nativescript_api->godot_nativescript_register_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
|
||||
godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *) typeid(T).hash_code());
|
||||
T::_register_methods();
|
||||
}
|
||||
|
||||
|
@ -130,8 +125,10 @@ void register_tool_class()
|
|||
godot_instance_destroy_func destroy = {};
|
||||
destroy.destroy_func = _godot_class_destroy_func<T>;
|
||||
|
||||
_TagDB::register_type(typeid(T).hash_code(), typeid(T).hash_code());
|
||||
|
||||
godot::nativescript_api->godot_nativescript_register_tool_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
|
||||
godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *) typeid(T).hash_code());
|
||||
T::_register_methods();
|
||||
}
|
||||
|
||||
|
@ -369,7 +366,7 @@ void register_property(const char *name, P (T::*var), P default_value, godot_met
|
|||
usage = (godot_property_usage_flags) ((int) usage | GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE);
|
||||
|
||||
if (def_val.get_type() == Variant::OBJECT) {
|
||||
Object *o = def_val;
|
||||
Object *o = get_wrapper<Object>(def_val.operator godot_object*());
|
||||
if (o && o->is_class("Resource")) {
|
||||
hint = (godot_property_hint) ((int) hint | GODOT_PROPERTY_HINT_RESOURCE_TYPE);
|
||||
hint_string = o->get_class();
|
||||
|
@ -490,6 +487,35 @@ void register_signal(String name, Args... varargs)
|
|||
register_signal<T>(name, Dictionary::make(varargs...));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef GODOT_CPP_NO_OBJECT_CAST
|
||||
template<class T>
|
||||
T *Object::cast_to(const Object *obj)
|
||||
{
|
||||
size_t have_tag = (size_t) godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
|
||||
|
||||
if (have_tag) {
|
||||
if (!godot::_TagDB::is_type_known((size_t) have_tag)) {
|
||||
have_tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_tag) {
|
||||
have_tag = obj->_type_tag;
|
||||
}
|
||||
|
||||
if (godot::_TagDB::is_type_compatible(typeid(T).hash_code(), have_tag)) {
|
||||
return (T::___CLASS_IS_SCRIPT) ? godot::as<T>(obj) : (T *) obj;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // GODOT_H
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
#include "String.hpp"
|
||||
#include "Array.hpp"
|
||||
|
||||
|
||||
namespace godot {
|
||||
|
||||
extern "C" const godot_gdnative_core_api_struct *api;
|
||||
extern "C" const godot_gdnative_ext_nativescript_api_struct *nativescript_api;
|
||||
extern "C" const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api;
|
||||
|
||||
extern "C" const void *gdnlib;
|
||||
|
||||
class Godot {
|
||||
|
||||
|
@ -21,6 +23,7 @@ public:
|
|||
static void gdnative_init(godot_gdnative_init_options *o);
|
||||
static void gdnative_terminate(godot_gdnative_terminate_options *o);
|
||||
static void nativescript_init(void *handle);
|
||||
static void nativescript_terminate(void *handle);
|
||||
|
||||
template <class... Args>
|
||||
static void print(const String& fmt, Args... values) {
|
||||
|
@ -32,6 +35,7 @@ public:
|
|||
|
||||
struct _RegisterState {
|
||||
static void *nativescript_handle;
|
||||
static int language_index;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "Variant.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "../Reference.hpp"
|
||||
#include "Reference.hpp"
|
||||
|
||||
namespace godot {
|
||||
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
void operator=(const Variant &p_variant) {
|
||||
|
||||
// TODO We need a safe cast
|
||||
Reference *refb = (Reference *) (Object *) p_variant;
|
||||
Reference *refb = (Reference *) T::___get_from_variant(p_variant);
|
||||
if (!refb) {
|
||||
unref();
|
||||
return;
|
||||
|
@ -156,7 +156,7 @@ public:
|
|||
|
||||
reference = nullptr;
|
||||
// TODO We need a safe cast
|
||||
Reference *refb = (Reference *) (Object *) p_variant;
|
||||
Reference *refb = (Reference *) T::___get_from_variant(p_variant);
|
||||
if (!refb) {
|
||||
unref();
|
||||
return;
|
||||
|
@ -180,14 +180,14 @@ public:
|
|||
if (reference && reference->unreference()) {
|
||||
|
||||
//memdelete(reference);
|
||||
delete reference;
|
||||
reference->free();
|
||||
}
|
||||
reference = nullptr;
|
||||
}
|
||||
|
||||
void instance() {
|
||||
//ref(memnew(T));
|
||||
ref(new T);
|
||||
ref(T::_new());
|
||||
}
|
||||
|
||||
Ref() {
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace godot {
|
|||
class NodePath;
|
||||
class Variant;
|
||||
class PoolByteArray;
|
||||
class PoolIntArray;
|
||||
class PoolRealArray;
|
||||
class PoolStringArray;
|
||||
class String;
|
||||
|
@ -120,6 +121,7 @@ public:
|
|||
String sha256_text() const;
|
||||
float similarity(String text) const;
|
||||
PoolStringArray split(String divisor, bool allow_empty = true) const;
|
||||
PoolIntArray split_ints(String divisor, bool allow_empty = true) const;
|
||||
PoolRealArray split_floats(String divisor, bool allow_empty = true) const;
|
||||
String strip_edges(bool left = true, bool right = true) const;
|
||||
String substr(int from, int len) const;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef TAGDB_HPP
|
||||
#define TAGDB_HPP
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace _TagDB {
|
||||
|
||||
void register_type(size_t type_tag, size_t base_type_tag);
|
||||
bool is_type_known(size_t type_tag);
|
||||
void register_global_type(const char *name, size_t type_tag, size_t base_type_tag);
|
||||
bool is_type_compatible(size_t type_tag, size_t base_type_tag);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TAGDB_HPP
|
|
@ -225,7 +225,7 @@ public:
|
|||
|
||||
operator NodePath() const;
|
||||
operator RID() const;
|
||||
operator Object*() const;
|
||||
operator godot_object*() const;
|
||||
|
||||
operator Dictionary() const;
|
||||
operator Array() const;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef WRAPPED_HPP
|
||||
#define WRAPPED_HPP
|
||||
|
||||
#include <gdnative/gdnative.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class _Wrapped {
|
||||
public:
|
||||
godot_object *_owner;
|
||||
size_t _type_tag;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WRAPPED_HPP
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -269,7 +269,7 @@ Color Color::html(const String& p_color)
|
|||
} else if (color.length()==6) {
|
||||
alpha=false;
|
||||
} else {
|
||||
ERR_PRINT(String("Invalid Color Code: ") + p_color);
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ Color Color::html(const String& p_color)
|
|||
if (alpha) {
|
||||
a=_parse_col(color,0);
|
||||
if (a<0) {
|
||||
ERR_PRINT("Invalid Color Code: "+p_color);
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
|
@ -286,17 +286,17 @@ Color Color::html(const String& p_color)
|
|||
|
||||
int r=_parse_col(color,from+0);
|
||||
if (r<0) {
|
||||
ERR_PRINT("Invalid Color Code: "+p_color);
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int g=_parse_col(color,from+2);
|
||||
if (g<0) {
|
||||
ERR_PRINT("Invalid Color Code: "+p_color);
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int b=_parse_col(color,from+4);
|
||||
if (b<0) {
|
||||
ERR_PRINT("Invalid Color Code: "+p_color);
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,35 @@
|
|||
|
||||
#include "String.hpp"
|
||||
|
||||
#include "Wrapped.hpp"
|
||||
|
||||
static GDCALLINGCONV void *wrapper_create(void *data, const void *type_tag, godot_object *instance)
|
||||
{
|
||||
godot::_Wrapped *wrapper_memory = (godot::_Wrapped *) godot::api->godot_alloc(sizeof(godot::_Wrapped));
|
||||
|
||||
if (!wrapper_memory)
|
||||
return NULL;
|
||||
wrapper_memory->_owner = instance;
|
||||
wrapper_memory->_type_tag = (size_t) type_tag;
|
||||
|
||||
return (void *) wrapper_memory;
|
||||
}
|
||||
|
||||
static GDCALLINGCONV void wrapper_destroy(void *data, void *wrapper)
|
||||
{
|
||||
if (wrapper)
|
||||
godot::api->godot_free(wrapper);
|
||||
}
|
||||
|
||||
namespace godot {
|
||||
|
||||
void *_RegisterState::nativescript_handle;
|
||||
int _RegisterState::language_index;
|
||||
const godot_gdnative_core_api_struct *api = nullptr;
|
||||
const godot_gdnative_ext_nativescript_api_struct *nativescript_api = nullptr;
|
||||
const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api = nullptr;
|
||||
|
||||
const void *gdnlib = NULL;
|
||||
|
||||
void Godot::print(const String& message)
|
||||
{
|
||||
|
@ -47,19 +71,33 @@ void Godot::print_error(const String& description, const String& function, const
|
|||
if (c_file != nullptr) godot::api->godot_free(c_file);
|
||||
}
|
||||
|
||||
void ___register_types();
|
||||
|
||||
void Godot::gdnative_init(godot_gdnative_init_options *options)
|
||||
{
|
||||
godot::api = options->api_struct;
|
||||
godot::gdnlib = options->gd_native_library;
|
||||
|
||||
// now find our extensions
|
||||
for (int i = 0; i < godot::api->num_extensions; i++) {
|
||||
switch (godot::api->extensions[i]->type) {
|
||||
case GDNATIVE_EXT_NATIVESCRIPT: {
|
||||
godot::nativescript_api = (godot_gdnative_ext_nativescript_api_struct *)godot::api->extensions[i];
|
||||
}; break;
|
||||
case GDNATIVE_EXT_NATIVESCRIPT: {
|
||||
godot::nativescript_api = (const godot_gdnative_ext_nativescript_api_struct *)godot::api->extensions[i];
|
||||
|
||||
const godot_gdnative_api_struct *extension = godot::nativescript_api->next;
|
||||
|
||||
while (extension) {
|
||||
if (extension->version.major == 1 && extension->version.minor == 1) {
|
||||
godot::nativescript_1_1_api = (const godot_gdnative_ext_nativescript_1_1_api_struct *) extension;
|
||||
}
|
||||
|
||||
extension = extension->next;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Godot::gdnative_terminate(godot_gdnative_terminate_options *options)
|
||||
|
@ -70,6 +108,19 @@ void Godot::gdnative_terminate(godot_gdnative_terminate_options *options)
|
|||
void Godot::nativescript_init(void *handle)
|
||||
{
|
||||
godot::_RegisterState::nativescript_handle = handle;
|
||||
|
||||
godot_instance_binding_functions binding_funcs = {};
|
||||
binding_funcs.alloc_instance_binding_data = wrapper_create;
|
||||
binding_funcs.free_instance_binding_data = wrapper_destroy;
|
||||
|
||||
godot::_RegisterState::language_index = godot::nativescript_1_1_api->godot_nativescript_register_instance_binding_data_functions(binding_funcs);
|
||||
|
||||
___register_types();
|
||||
}
|
||||
|
||||
};
|
||||
void Godot::nativescript_terminate(void *handle)
|
||||
{
|
||||
godot::nativescript_1_1_api->godot_nativescript_unregister_instance_binding_data_functions(godot::_RegisterState::language_index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ bool String::begins_with_char_array(const char *p_char_array) const {
|
|||
PoolStringArray String::bigrams() const {
|
||||
godot_array arr = godot::api->godot_string_bigrams(&_godot_string);
|
||||
|
||||
return *(PoolStringArray *)&arr;
|
||||
return *(Array *)&arr;
|
||||
}
|
||||
|
||||
String String::c_escape() const {
|
||||
|
@ -479,13 +479,19 @@ float String::similarity(String text) const {
|
|||
PoolStringArray String::split(String divisor, bool allow_empty) const {
|
||||
godot_array arr = godot::api->godot_string_split(&_godot_string, &divisor._godot_string);
|
||||
|
||||
return *(PoolStringArray *)&arr;
|
||||
return *(Array *)&arr;
|
||||
}
|
||||
|
||||
PoolIntArray String::split_ints(String divisor, bool allow_empty) const {
|
||||
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
|
||||
|
||||
return *(Array *)&arr;
|
||||
}
|
||||
|
||||
PoolRealArray String::split_floats(String divisor, bool allow_empty) const {
|
||||
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
|
||||
|
||||
return *(PoolRealArray *)&arr;
|
||||
return *(Array *)&arr;
|
||||
}
|
||||
|
||||
String String::strip_edges(bool left, bool right) const {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include "TagDB.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <GodotGlobal.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace _TagDB {
|
||||
|
||||
std::unordered_map<size_t, size_t> parent_to;
|
||||
|
||||
void register_type(size_t type_tag, size_t base_type_tag)
|
||||
{
|
||||
if (type_tag == base_type_tag) {
|
||||
return;
|
||||
}
|
||||
parent_to[type_tag] = base_type_tag;
|
||||
}
|
||||
|
||||
bool is_type_known(size_t type_tag)
|
||||
{
|
||||
return parent_to.find(type_tag) != parent_to.end();
|
||||
}
|
||||
|
||||
void register_global_type(const char *name, size_t type_tag, size_t base_type_tag)
|
||||
{
|
||||
|
||||
godot::nativescript_1_1_api->godot_nativescript_set_global_type_tag(godot::_RegisterState::language_index, name, (const void *) type_tag);
|
||||
|
||||
register_type(type_tag, base_type_tag);
|
||||
}
|
||||
|
||||
bool is_type_compatible(size_t ask_tag, size_t have_tag)
|
||||
{
|
||||
|
||||
if (have_tag == 0)
|
||||
return false;
|
||||
|
||||
size_t tag = have_tag;
|
||||
|
||||
while (tag != 0) {
|
||||
if (tag == ask_tag)
|
||||
return true;
|
||||
|
||||
tag = parent_to[tag];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
#include "Defs.hpp"
|
||||
#include "CoreTypes.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "Object.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -141,7 +142,7 @@ Variant::Variant(const RID& p_rid)
|
|||
|
||||
Variant::Variant(const Object* p_object)
|
||||
{
|
||||
godot::api->godot_variant_new_object(&_godot_variant, (godot_object *) p_object);
|
||||
godot::api->godot_variant_new_object(&_godot_variant, p_object->_owner);
|
||||
}
|
||||
|
||||
Variant::Variant(const Dictionary& p_dictionary)
|
||||
|
@ -363,9 +364,8 @@ Variant::operator PoolColorArray() const
|
|||
godot_pool_color_array s = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
|
||||
return *(PoolColorArray *) &s;
|
||||
}
|
||||
Variant::operator Object*() const {
|
||||
godot_object *o = godot::api->godot_variant_as_object(&_godot_variant);
|
||||
return (Object *) o;
|
||||
Variant::operator godot_object*() const {
|
||||
return godot::api->godot_variant_as_object(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::Type Variant::get_type() const
|
||||
|
|
|
@ -229,12 +229,12 @@ real_t Vector3::length_squared() const
|
|||
|
||||
real_t Vector3::distance_squared_to(const Vector3& b) const
|
||||
{
|
||||
return (b-*this).length();
|
||||
return (b-*this).length_squared();
|
||||
}
|
||||
|
||||
real_t Vector3::distance_to(const Vector3& b) const
|
||||
{
|
||||
return (b-*this).length_squared();
|
||||
return (b-*this).length();
|
||||
}
|
||||
|
||||
real_t Vector3::dot(const Vector3& b) const
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
Loading…
Reference in New Issue