diff options
| -rw-r--r-- | modules/gdnative/gdnative.cpp | 1362 | ||||
| -rw-r--r-- | modules/gdnative/gdnative.h | 396 | ||||
| -rw-r--r-- | modules/gdnative/godot/array.cpp (renamed from modules/gdnative/godot/godot_array.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/array.h (renamed from modules/gdnative/godot/godot_array.h) | 15 | ||||
| -rw-r--r-- | modules/gdnative/godot/basis.cpp (renamed from modules/gdnative/godot/godot_basis.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/basis.h (renamed from modules/gdnative/godot/godot_basis.h) | 13 | ||||
| -rw-r--r-- | modules/gdnative/godot/color.cpp (renamed from modules/gdnative/godot/godot_color.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/color.h (renamed from modules/gdnative/godot/godot_color.h) | 12 | ||||
| -rw-r--r-- | modules/gdnative/godot/dictionary.cpp (renamed from modules/gdnative/godot/godot_dictionary.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/dictionary.h (renamed from modules/gdnative/godot/godot_dictionary.h) | 14 | ||||
| -rw-r--r-- | modules/gdnative/godot/gdnative.cpp (renamed from modules/gdnative/godot.cpp) | 70 | ||||
| -rw-r--r-- | modules/gdnative/godot/gdnative.h | 298 | ||||
| -rw-r--r-- | modules/gdnative/godot/icon.png.import | 23 | ||||
| -rw-r--r-- | modules/gdnative/godot/node_path.cpp (renamed from modules/gdnative/godot/godot_node_path.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/node_path.h (renamed from modules/gdnative/godot/godot_node_path.h) | 12 | ||||
| -rw-r--r-- | modules/gdnative/godot/plane.cpp (renamed from modules/gdnative/godot/godot_plane.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/plane.h (renamed from modules/gdnative/godot/godot_plane.h) | 12 | ||||
| -rw-r--r-- | modules/gdnative/godot/pool_arrays.cpp (renamed from modules/gdnative/godot/godot_pool_arrays.cpp) | 10 | ||||
| -rw-r--r-- | modules/gdnative/godot/pool_arrays.h (renamed from modules/gdnative/godot/godot_pool_arrays.h) | 61 | ||||
| -rw-r--r-- | modules/gdnative/godot/quat.cpp (renamed from modules/gdnative/godot/godot_quat.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/quat.h (renamed from modules/gdnative/godot/godot_quat.h) | 12 | ||||
| -rw-r--r-- | modules/gdnative/godot/rect2.cpp (renamed from modules/gdnative/godot/godot_rect2.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/rect2.h (renamed from modules/gdnative/godot/godot_rect2.h) | 6 | ||||
| -rw-r--r-- | modules/gdnative/godot/rect3.cpp (renamed from modules/gdnative/godot/godot_rect3.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/rect3.h (renamed from modules/gdnative/godot/godot_rect3.h) | 14 | ||||
| -rw-r--r-- | modules/gdnative/godot/rid.cpp (renamed from modules/gdnative/godot/godot_rid.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/rid.h (renamed from modules/gdnative/godot/godot_rid.h) | 10 | ||||
| -rw-r--r-- | modules/gdnative/godot/string.cpp (renamed from modules/gdnative/godot/godot_string.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/string.h (renamed from modules/gdnative/godot/godot_string.h) | 11 | ||||
| -rw-r--r-- | modules/gdnative/godot/transform.cpp (renamed from modules/gdnative/godot/godot_transform.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/transform.h (renamed from modules/gdnative/godot/godot_transform.h) | 16 | ||||
| -rw-r--r-- | modules/gdnative/godot/transform2d.cpp (renamed from modules/gdnative/godot/godot_transform2d.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/transform2d.h (renamed from modules/gdnative/godot/godot_transform2d.h) | 14 | ||||
| -rw-r--r-- | modules/gdnative/godot/variant.cpp (renamed from modules/gdnative/godot/godot_variant.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/variant.h (renamed from modules/gdnative/godot/godot_variant.h) | 47 | ||||
| -rw-r--r-- | modules/gdnative/godot/vector2.cpp (renamed from modules/gdnative/godot/godot_vector2.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/vector2.h (renamed from modules/gdnative/godot/godot_vector2.h) | 10 | ||||
| -rw-r--r-- | modules/gdnative/godot/vector3.cpp (renamed from modules/gdnative/godot/godot_vector3.cpp) | 4 | ||||
| -rw-r--r-- | modules/gdnative/godot/vector3.h (renamed from modules/gdnative/godot/godot_vector3.h) | 12 | ||||
| -rw-r--r-- | modules/gdnative/register_types.cpp | 54 | ||||
| -rw-r--r-- | modules/nativescript/SCsub | 10 | ||||
| -rw-r--r-- | modules/nativescript/api_generator.cpp (renamed from modules/gdnative/api_generator.cpp) | 0 | ||||
| -rw-r--r-- | modules/nativescript/api_generator.h (renamed from modules/gdnative/api_generator.h) | 0 | ||||
| -rw-r--r-- | modules/nativescript/config.py | 8 | ||||
| -rw-r--r-- | modules/nativescript/godot_nativescript.cpp | 205 | ||||
| -rw-r--r-- | modules/nativescript/godot_nativescript.h (renamed from modules/gdnative/godot.h) | 267 | ||||
| -rw-r--r-- | modules/nativescript/nativescript.cpp | 1088 | ||||
| -rw-r--r-- | modules/nativescript/nativescript.h | 281 | ||||
| -rw-r--r-- | modules/nativescript/register_types.cpp | 93 | ||||
| -rw-r--r-- | modules/nativescript/register_types.h | 31 | 
50 files changed, 2544 insertions, 2007 deletions
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 214164ef89..65bfbb0ff7 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -36,725 +36,54 @@  #include "project_settings.h"  #include "scene/main/scene_tree.h" -#include "scene/resources/scene_format_text.h" -#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) -#include "api_generator.h" -#endif +const String init_symbol = "godot_gdnative_init"; +const String terminate_symbol = "godot_gdnative_terminate"; -#ifdef TOOLS_ENABLED -#include "editor/editor_node.h" -#endif +String GDNativeLibrary::platform_names[NUM_PLATFORMS] = { +	"X11_32bit", +	"X11_64bit", +	"Windows_32bit", +	"Windows_64bit", +	"OSX", -Error NativeLibrary::initialize(NativeLibrary *&p_native_lib, const StringName p_path) { +	"Android", +	"iOS", -	if (GDNativeScriptLanguage::get_singleton()->initialized_libraries.has(p_path)) { -		p_native_lib = GDNativeScriptLanguage::get_singleton()->initialized_libraries[p_path]; -		return OK; -	} - -	NativeLibrary *lib = memnew(NativeLibrary); -	lib->path = p_path; - -	p_native_lib = lib; - -	// Open the file - -	Error error; -	error = OS::get_singleton()->open_dynamic_library(p_path, lib->handle); -	if (error) return error; -	ERR_FAIL_COND_V(!lib->handle, ERR_BUG); - -	// Get the method - -	void *library_init; -	error = OS::get_singleton()->get_dynamic_library_symbol_handle(lib->handle, GDNativeScriptLanguage::get_init_symbol_name(), library_init); -	if (error) return error; -	ERR_FAIL_COND_V(!library_init, ERR_BUG); - -	void (*library_init_fpointer)(godot_native_init_options *) = (void (*)(godot_native_init_options *))library_init; - -	godot_native_init_options options; - -	options.in_editor = SceneTree::get_singleton()->is_editor_hint(); -	options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); -	options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); -	options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE); - -	library_init_fpointer(&options); // Catch errors? - -	GDNativeScriptLanguage::get_singleton()->initialized_libraries[p_path] = lib; - -	return OK; -} - -Error NativeLibrary::terminate(NativeLibrary *&p_native_lib) { - -	if (!GDNativeScriptLanguage::get_singleton()->initialized_libraries.has(p_native_lib->path)) { -		OS::get_singleton()->close_dynamic_library(p_native_lib->handle); -		p_native_lib->handle = 0; -		return OK; -	} - -	Error error = OK; -	void *library_terminate; -	error = OS::get_singleton()->get_dynamic_library_symbol_handle(p_native_lib->handle, GDNativeScriptLanguage::get_terminate_symbol_name(), library_terminate); -	if (!error) { - -		void (*library_terminate_pointer)(godot_native_terminate_options *) = (void (*)(godot_native_terminate_options *))library_terminate; - -		godot_native_terminate_options options; -		options.in_editor = SceneTree::get_singleton()->is_editor_hint(); - -		library_terminate_pointer(&options); -	} - -	GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path); - -	OS::get_singleton()->close_dynamic_library(p_native_lib->handle); -	p_native_lib->handle = 0; - -	return OK; -} - -// Script -#ifdef TOOLS_ENABLED - -void GDNativeScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { -	ERR_FAIL_COND(!script_data); - -	List<PropertyInfo> pinfo; -	Map<StringName, Variant> values; - -	for (Map<StringName, GDNativeScriptData::Property>::Element *E = script_data->properties.front(); E; E = E->next()) { -		PropertyInfo p = E->get().info; -		p.name = String(E->key()); -		pinfo.push_back(p); -		values[p.name] = E->get().default_value; -	} - -	p_placeholder->update(pinfo, values); -} - -void GDNativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { - -	placeholders.erase(p_placeholder); -} - -#endif - -bool GDNativeScript::can_instance() const { -#ifdef TOOLS_ENABLED -	return script_data || (!is_tool() && !ScriptServer::is_scripting_enabled()); -#else -	// allow defaultlibrary without editor features -	if (!library.is_valid()) { -		String path = GLOBAL_GET("gdnative/default_gdnativelibrary"); - -		RES lib = ResourceLoader::load(path); - -		if (lib.is_valid() && lib->cast_to<GDNativeLibrary>()) { -			return true; -		} -	} - -	return script_data; -#endif -	//return script_data || (!tool && !ScriptServer::is_scripting_enabled()); -	// change to true enable in editor stuff. -} - -Ref<Script> GDNativeScript::get_base_script() const { -	Ref<GDNativeScript> base_script; -	base_script->library = library; -	base_script->script_data = script_data; -	base_script->script_name = script_data->base; -	return base_script; -} - -StringName GDNativeScript::get_instance_base_type() const { -	return script_data->base_native_type; -} - -ScriptInstance *GDNativeScript::instance_create(Object *p_this) { - -#ifdef TOOLS_ENABLED - -	// find a good way to initialize stuff in the editor -	if (!ScriptServer::is_scripting_enabled() && !is_tool()) { -		// placeholder, for nodes. But for tools we want the real thing - -		PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(GDNativeScriptLanguage::singleton, Ref<Script>((Script *)this), p_this)); -		placeholders.insert(sins); - -		if (!library.is_valid()) -			return sins; - -		if (!library->native_library) { -			Error err = library->_initialize(); -			if (err != OK) { -				return sins; -			} -		} - -		if (!script_data) { -			script_data = library->get_script_data(script_name); -		} -		if (script_data && script_data->create_func.create_func) { -			script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); -		} - -		_update_placeholder(sins); - -		return sins; -	} - -#endif - -	if (!library.is_valid()) { -		String path = GLOBAL_GET("gdnative/default_gdnativelibrary"); - -		RES lib = ResourceLoader::load(path); - -		if (lib.is_valid() && lib->cast_to<GDNativeLibrary>()) { -			set_library(lib); -		} -	} - -	GDNativeInstance *new_instance = memnew(GDNativeInstance); - -	new_instance->owner = p_this; -	new_instance->script = Ref<GDNativeScript>(this); - -#ifndef TOOLS_ENABLED -	if (!ScriptServer::is_scripting_enabled()) { -		new_instance->userdata = 0; -	} else { -		new_instance->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); -	} -#else -	new_instance->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); -#endif - -	instances.insert(p_this); -	return new_instance; -} - -bool GDNativeScript::instance_has(const Object *p_this) const { -	return instances.has((Object *)p_this); // TODO -} - -bool GDNativeScript::has_source_code() const { -	return false; -} - -String GDNativeScript::get_source_code() const { -	return ""; -} - -Error GDNativeScript::reload(bool p_keep_state) { -	return FAILED; -} - -bool GDNativeScript::has_method(const StringName &p_method) const { -	if (!script_data) -		return false; -	GDNativeScriptData *data = script_data; - -	while (data) { -		if (data->methods.has(p_method)) -			return true; - -		data = data->base_data; -	} - -	return false; -} - -MethodInfo GDNativeScript::get_method_info(const StringName &p_method) const { -	if (!script_data) -		return MethodInfo(); -	GDNativeScriptData *data = script_data; - -	while (data) { -		if (data->methods.has(p_method)) -			return data->methods[p_method].info; - -		data = data->base_data; -	} - -	ERR_FAIL_COND_V(!script_data->methods.has(p_method), MethodInfo()); -	return MethodInfo(); -} - -void GDNativeScript::get_script_method_list(List<MethodInfo> *p_list) const { -	if (!script_data) return; - -	Set<MethodInfo> methods; -	GDNativeScriptData *data = script_data; - -	while (data) { -		for (Map<StringName, GDNativeScriptData::Method>::Element *E = data->methods.front(); E; E = E->next()) { -			methods.insert(E->get().info); -		} -		data = data->base_data; -	} - -	for (Set<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { -		p_list->push_back(E->get()); -	} -} - -void GDNativeScript::get_script_property_list(List<PropertyInfo> *p_list) const { -	if (!script_data) return; - -	Set<PropertyInfo> properties; -	GDNativeScriptData *data = script_data; - -	while (data) { -		for (Map<StringName, GDNativeScriptData::Property>::Element *E = data->properties.front(); E; E = E->next()) { -			properties.insert(E->get().info); -		} -		data = data->base_data; -	} - -	for (Set<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { -		p_list->push_back(E->get()); -	} -} - -bool GDNativeScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { -	if (!script_data) return false; - -	GDNativeScriptData *data = script_data; - -	while (data) { -		if (data->properties.has(p_property)) { -			r_value = data->properties[p_property].default_value; -			return true; -		} - -		data = data->base_data; -	} - -	return false; -} - -bool GDNativeScript::is_tool() const { -	ERR_FAIL_COND_V(!script_data, false); -	return script_data->is_tool; -} - -String GDNativeScript::get_node_type() const { -	return ""; // ? -} - -ScriptLanguage *GDNativeScript::get_language() const { -	return GDNativeScriptLanguage::singleton; -} - -bool GDNativeScript::has_script_signal(const StringName &p_signal) const { -	if (!script_data) -		return false; - -	GDNativeScriptData *data = script_data; - -	while (data) { -		if (data->signals_.has(p_signal)) { -			return true; -		} - -		data = data->base_data; -	} - -	return false; -} - -void GDNativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const { -	if (!script_data) -		return; - -	Set<MethodInfo> signals_; -	GDNativeScriptData *data = script_data; - -	while (data) { - -		for (Map<StringName, GDNativeScriptData::Signal>::Element *S = data->signals_.front(); S; S = S->next()) { -			signals_.insert(S->get().signal); -		} - -		data = data->base_data; -	} - -	for (Set<MethodInfo>::Element *E = signals_.front(); E; E = E->next()) { -		r_signals->push_back(E->get()); -	} -} - -Variant GDNativeScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - -	/* STEP 1, CREATE */ - -	if (!library.is_valid() || ((String)script_name).empty() || !script_data) { -		r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; -		return Variant(); -	} - -	r_error.error = Variant::CallError::CALL_OK; -	REF ref; -	Object *owner = NULL; - -	GDNativeScriptData *_baseptr = script_data; -	while (_baseptr->base_data) { -		_baseptr = _baseptr->base_data; -	} - -	if (!(_baseptr->base_native_type == "")) { -		owner = ClassDB::instance(_baseptr->base_native_type); -	} else { -		owner = memnew(Reference); //by default, no base means use reference -	} - -	Reference *r = owner->cast_to<Reference>(); -	if (r) { -		ref = REF(r); -	} - -	// GDScript does it like this: _create_instance(p_args, p_argcount, owner, r != NULL, r_error); -	// @Todo support varargs for constructors. -	GDNativeInstance *instance = (GDNativeInstance *)instance_create(owner); - -	owner->set_script_instance(instance); -	if (!instance) { -		if (ref.is_null()) { -			memdelete(owner); //no owner, sorry -		} -		return Variant(); -	} - -	if (ref.is_valid()) { -		return ref; -	} else { -		return owner; -	} -} - -Ref<GDNativeLibrary> GDNativeScript::get_library() const { -	return library; -} - -void GDNativeScript::set_library(Ref<GDNativeLibrary> p_library) { -	library = p_library; - -#ifdef TOOLS_ENABLED -	if (!ScriptServer::is_scripting_enabled()) -		return; -#endif -	if (library.is_valid()) { -		Error initalize_status = library->_initialize(); -		ERR_FAIL_COND(initalize_status != OK); -		if (script_name) { -			script_data = library->native_library->scripts[script_name]; -			ERR_FAIL_COND(!script_data); -		} -	} -} - -StringName GDNativeScript::get_script_name() const { -	return script_name; -} - -void GDNativeScript::set_script_name(StringName p_script_name) { -	script_name = p_script_name; - -	if (library.is_valid()) { -#ifdef TOOLS_ENABLED -		if (!library->native_library) { -			library->_initialize(); -		} -#endif -		if (library->native_library) { -			script_data = library->get_script_data(script_name); -			ERR_FAIL_COND(!script_data); -		} -	} -} - -void GDNativeScript::_bind_methods() { -	ClassDB::bind_method(D_METHOD("get_library:GDNativeLibrary"), &GDNativeScript::get_library); -	ClassDB::bind_method(D_METHOD("set_library", "library:GDNativeLibrary"), &GDNativeScript::set_library); -	ClassDB::bind_method(D_METHOD("get_script_name"), &GDNativeScript::get_script_name); -	ClassDB::bind_method(D_METHOD("set_script_name", "script_name"), &GDNativeScript::set_script_name); - -	ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &GDNativeScript::_new, MethodInfo(Variant::OBJECT, "new")); - -	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library"); -	ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "script_name"), "set_script_name", "get_script_name"); -} - -GDNativeScript::GDNativeScript() { -	script_data = NULL; -	GDNativeScriptLanguage::get_singleton()->script_list.insert(this); -} - -GDNativeScript::~GDNativeScript() { -	//hmm -	GDNativeScriptLanguage::get_singleton()->script_list.erase(this); -} - -// Library - -GDNativeLibrary *GDNativeLibrary::currently_initialized_library = NULL; - -GDNativeLibrary *GDNativeLibrary::get_currently_initialized_library() { -	return currently_initialized_library; -} - -static const char *_dl_platforms_info[] = { -	"|unix|so|Unix", -	"unix|x11|so|X11", -	"unix|server|so|Server", -	"unix|android|so|Android", -	"unix|haiku|so|Haiku", // Right? -	"|mac|dylib|Mac", -	"mac|ios|dylib|iOS", -	"mac|osx|dylib|OSX", -	"|html5|js|HTML5", -	"|windows|dll|Windows", -	"windows|uwp|dll|UWP", -	NULL // Finishing condition +	"WebAssembly"  }; +String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = { +	"so", +	"so", +	"dll", +	"dll", +	"dylib", -void GDNativeLibrary::set_platform_file(StringName p_platform, String p_file) { -	if (p_file.empty()) { -		platform_files.erase(p_platform); -	} else { -		platform_files[p_platform] = p_file; -	} -} - -String GDNativeLibrary::get_platform_file(StringName p_platform) const { -	if (platform_files.has(p_platform)) { -		return platform_files[p_platform]; -	} else { -		return ""; -	} -} - -Error GDNativeLibrary::_initialize() { -	_THREAD_SAFE_METHOD_ - -	// Get the file - -	const String platform_name = OS::get_singleton()->get_name(); -	String platform_file(""); -	char **platform_info = (char **)_dl_platforms_info; - -	if (platform_files.has(platform_name.to_lower())) { -		platform_file = platform_files[platform_name.to_lower()]; -	} - -	while (*platform_info) { -		String platform_info_string(*platform_info); - -		if (platform_name == platform_info_string.get_slicec('|', 3)) { -			String platform_key = platform_info_string.get_slicec('|', 1); -			String fallback_platform_key = platform_info_string.get_slicec('|', 0); - -			if (platform_files.has(platform_key)) { -				platform_file = platform_files[platform_key]; -			} else if (!fallback_platform_key.empty() && platform_files.has(fallback_platform_key)) { -				platform_file = platform_files[fallback_platform_key]; -			} else { -				return ERR_UNAVAILABLE; -			} -		} -		platform_info++; -	} -	ERR_FAIL_COND_V(platform_file == "", ERR_DOES_NOT_EXIST); - -	StringName path = ProjectSettings::get_singleton()->globalize_path(platform_file); - -	GDNativeLibrary::currently_initialized_library = this; - -	Error ret = NativeLibrary::initialize(native_library, path); -	native_library->dllib = this; - -	GDNativeLibrary::currently_initialized_library = NULL; +	"so", +	"dylib", -	return ret; -} - -Error GDNativeLibrary::_terminate() { -	ERR_FAIL_COND_V(!native_library, ERR_BUG); -	ERR_FAIL_COND_V(!native_library->handle, ERR_BUG); - -	// de-init stuff - -	for (Map<StringName, GDNativeScriptData *>::Element *E = native_library->scripts.front(); E; E = E->next()) { -		for (Map<StringName, GDNativeScriptData::Method>::Element *M = E->get()->methods.front(); M; M = M->next()) { -			if (M->get().method.free_func) { -				M->get().method.free_func(M->get().method.method_data); -			} -		} -		if (E->get()->create_func.free_func) { -			E->get()->create_func.free_func(E->get()->create_func.method_data); -		} -		if (E->get()->destroy_func.free_func) { -			E->get()->destroy_func.free_func(E->get()->destroy_func.method_data); -		} - -		for (Set<GDNativeScript *>::Element *S = GDNativeScriptLanguage::get_singleton()->script_list.front(); S; S = S->next()) { -			if (S->get()->script_data == E->get()) { -				S->get()->script_data = NULL; -			} -		} - -		memdelete(E->get()); -	} - -	Error ret = NativeLibrary::terminate(native_library); -	native_library->scripts.clear(); - -	return ret; -} - -void GDNativeLibrary::_register_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) { -	ERR_FAIL_COND(!native_library); -	ERR_FAIL_COND(native_library->scripts.has(p_name)); - -	GDNativeScriptData *s = memnew(GDNativeScriptData); -	s->base = p_base; -	s->create_func = p_instance_func; -	s->destroy_func = p_destroy_func; -	Map<StringName, GDNativeScriptData *>::Element *E = native_library->scripts.find(p_base); -	if (E) { -		s->base_data = E->get(); -		s->base_native_type = s->base_data->base_native_type; -	} else { -		if (!ClassDB::class_exists(p_base)) { -			memdelete(s); -			ERR_EXPLAIN("Invalid base for registered type '" + p_name + "'"); -			ERR_FAIL(); -		} -		s->base_native_type = p_base; -	} - -	native_library->scripts.insert(p_name, s); -} - -void GDNativeLibrary::_register_tool_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) { -	ERR_FAIL_COND(!native_library); -	ERR_FAIL_COND(native_library->scripts.has(p_name)); - -	GDNativeScriptData *s = memnew(GDNativeScriptData); -	s->base = p_base; -	s->create_func = p_instance_func; -	s->destroy_func = p_destroy_func; -	s->is_tool = true; -	Map<StringName, GDNativeScriptData *>::Element *E = native_library->scripts.find(p_base); -	if (E) { -		s->base_data = E->get(); -		s->base_native_type = s->base_data->base_native_type; -	} else { -		if (!ClassDB::class_exists(p_base)) { -			memdelete(s); -			ERR_EXPLAIN("Invalid base for registered type '" + p_name + "'"); -			ERR_FAIL(); -		} -		s->base_native_type = p_base; -	} - -	native_library->scripts.insert(p_name, s); -} - -void GDNativeLibrary::_register_script_method(const StringName p_name, const StringName p_method, godot_method_attributes p_attr, godot_instance_method p_func, MethodInfo p_info) { -	ERR_FAIL_COND(!native_library); -	ERR_FAIL_COND(!native_library->scripts.has(p_name)); - -	p_info.name = p_method; -	GDNativeScriptData::Method method; - -	method = GDNativeScriptData::Method(p_func, p_info, p_attr.rpc_type); - -	native_library->scripts[p_name]->methods.insert(p_method, method); -} - -void GDNativeLibrary::_register_script_property(const StringName p_name, const String p_path, godot_property_attributes *p_attr, godot_property_set_func p_setter, godot_property_get_func p_getter) { -	ERR_FAIL_COND(!native_library); -	ERR_FAIL_COND(!native_library->scripts.has(p_name)); - -	GDNativeScriptData::Property p; - -	PropertyInfo pi; -	pi.name = p_path; - -	if (p_attr != NULL) { -		pi = PropertyInfo((Variant::Type)p_attr->type, p_path, (PropertyHint)p_attr->hint, *(String *)&p_attr->hint_string, p_attr->usage); +	"wasm" +}; -		p = GDNativeScriptData::Property(p_setter, p_getter, pi, *(Variant *)&p_attr->default_value, p_attr->rset_type); -	} +// TODO(karroffel): make this actually do something lol. +GDNativeLibrary::Platform GDNativeLibrary::current_platform = X11_64BIT; -	native_library->scripts[p_name]->properties.insert(p_path, p); +GDNativeLibrary::GDNativeLibrary() +	: library_paths() {  } -void GDNativeLibrary::_register_script_signal(const StringName p_name, const godot_signal *p_signal) { -	ERR_FAIL_COND(!native_library); -	ERR_FAIL_COND(!native_library->scripts.has(p_name)); -	ERR_FAIL_COND(!p_signal); - -	GDNativeScriptData::Signal signal; - -	signal.signal.name = *(String *)&p_signal->name; - -	{ -		List<PropertyInfo> arguments; -		for (int i = 0; i < p_signal->num_args; i++) { -			PropertyInfo info; -			godot_signal_argument attrib = p_signal->args[i]; - -			String *name = (String *)&attrib.name; -			info.name = *name; -			info.type = (Variant::Type)attrib.type; -			info.hint = (PropertyHint)attrib.hint; -			info.hint_string = *(String *)&attrib.hint_string; -			info.usage = attrib.usage; - -			arguments.push_back(info); -		} - -		signal.signal.arguments = arguments; -	} - -	{ -		Vector<Variant> default_arguments; -		for (int i = 0; i < p_signal->num_default_args; i++) { -			Variant *v; -			godot_signal_argument attrib = p_signal->args[i]; - -			v = (Variant *)&attrib.default_value; - -			default_arguments.push_back(*v); -		} - -		signal.signal.default_arguments = default_arguments; -	} - -	native_library->scripts[p_name]->signals_.insert(*(String *)&p_signal->name, signal); +GDNativeLibrary::~GDNativeLibrary() {  } -GDNativeScriptData *GDNativeLibrary::get_script_data(const StringName p_name) { -	ERR_FAIL_COND_V(!native_library, NULL); - -	ERR_FAIL_COND_V(!native_library->scripts.has(p_name), NULL); - -	return native_library->scripts[p_name]; +void GDNativeLibrary::_bind_methods() { +	ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path); +	ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);  }  bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) {  	String name = p_name;  	if (name.begins_with("platform/")) { -		set_platform_file(name.get_slice("/", 1), p_value); +		set_library_path(name.get_slice("/", 1), p_value);  		return true;  	}  	return false; @@ -763,582 +92,231 @@ bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) {  bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_ret) const {  	String name = p_name;  	if (name.begins_with("platform/")) { -		r_ret = get_platform_file(name.get_slice("/", 1)); +		r_ret = get_library_path(name.get_slice("/", 1));  		return true;  	}  	return false;  }  void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { -	char **platform_info = (char **)_dl_platforms_info; - -	Set<String> registered_platform_names; -	{ -		List<StringName> ep; -		// ep.push_back("X11"); -		// EditorImportExport::get_singleton()->get_export_platforms(&ep); - -		// @Todo -		// get export platforms with the new export system somehow. -		for (List<StringName>::Element *E = ep.front(); E; E = E->next()) { -			registered_platform_names.insert(String(E->get()).to_lower()); -		} -	} - -	while (*platform_info) { -		String platform_info_string(*platform_info); -		String fallback_platform_key = platform_info_string.get_slicec('|', 0); -		String platform_key = platform_info_string.get_slicec('|', 1); -		String platform_extension = platform_info_string.get_slicec('|', 2); -		String platform_name = platform_info_string.get_slicec('|', 3); - -		registered_platform_names.erase(platform_name); - -		if (fallback_platform_key.empty()) { -			p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension)); - -		} else { -			if (platform_files.has(platform_key)) { -				p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED)); -			} else { -				p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE)); -			} -		} -		platform_info++; -	} - -	while (registered_platform_names.size()) { -		const String platform_name = registered_platform_names.front()->get(); -		registered_platform_names.erase(platform_name); -		p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_name.to_lower(), PROPERTY_HINT_FILE, "*")); -	} -} - -void GDNativeLibrary::_notification(int what) { -	// TODO -} - -void GDNativeLibrary::_bind_methods() { -	ClassDB::bind_method(D_METHOD("set_platform_file", "platform", "file"), &GDNativeLibrary::set_platform_file); -	ClassDB::bind_method(D_METHOD("get_platform_file", "platform"), &GDNativeLibrary::get_platform_file); -} - -GDNativeLibrary::GDNativeLibrary() { -	native_library = NULL; -} - -GDNativeLibrary::~GDNativeLibrary() { - -	if (!native_library) { -		return; -	} - -	if (native_library->handle) { -		_terminate(); +	for (int i = 0; i < NUM_PLATFORMS; i++) { +		p_list->push_back(PropertyInfo(Variant::STRING, +				"platform/" + platform_names[i], +				PROPERTY_HINT_FILE, +				"*." + platform_lib_ext[i]));  	}  } -// Instance - -bool GDNativeInstance::set(const StringName &p_name, const Variant &p_value) { -	if (!script->script_data) -		return false; -	if (script->script_data->properties.has(p_name)) { -		script->script_data->properties[p_name].setter.set_func((godot_object *)owner, script->script_data->properties[p_name].setter.method_data, userdata, *(godot_variant *)&p_value); -		return true; +void GDNativeLibrary::set_library_path(StringName p_platform, String p_path) { +	int i; +	for (i = 0; i <= NUM_PLATFORMS; i++) { +		if (i == NUM_PLATFORMS) break; +		if (platform_names[i] == p_platform) { +			break; +		}  	} -	Map<StringName, GDNativeScriptData::Method>::Element *E = script->script_data->methods.find("_set"); -	if (E) { -		Variant name = p_name; -		const Variant *args[2] = { &name, &p_value }; - -		E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, 2, (godot_variant **)args); -		return true; +	if (i == NUM_PLATFORMS) { +		ERR_EXPLAIN(String("No such platform: ") + p_platform); +		ERR_FAIL();  	} -	return false; +	library_paths[i] = p_path;  } -bool GDNativeInstance::get(const StringName &p_name, Variant &r_ret) const { -	if (!script->script_data) -		return false; -	if (script->script_data->properties.has(p_name)) { -		godot_variant value = script->script_data->properties[p_name].getter.get_func((godot_object *)owner, script->script_data->properties[p_name].getter.method_data, userdata); -		r_ret = *(Variant *)&value; -		godot_variant_destroy(&value); -		return true; -	} - -	Map<StringName, GDNativeScriptData::Method>::Element *E = script->script_data->methods.find("_get"); -	if (E) { -		Variant name = p_name; -		const Variant *args[1] = { &name }; - -		godot_variant result = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, 1, (godot_variant **)args); -		if (((Variant *)&result)->get_type() != Variant::NIL) { -			r_ret = *(Variant *)&result; -			godot_variant_destroy(&result); -			return true; +String GDNativeLibrary::get_library_path(StringName p_platform) const { +	int i; +	for (i = 0; i <= NUM_PLATFORMS; i++) { +		if (i == NUM_PLATFORMS) break; +		if (platform_names[i] == p_platform) { +			break;  		} -		godot_variant_destroy(&result);  	} -	return false; -} - -void GDNativeInstance::get_property_list(List<PropertyInfo> *p_properties) const { -	script->get_script_property_list(p_properties); -	// TODO: dynamic properties - -	Map<StringName, GDNativeScriptData::Method>::Element *E = script->script_data->methods.find("_get_property_list"); -	if (E) { -		godot_variant result = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, 0, NULL); -		Variant ret = *(Variant *)&result; -		godot_variant_destroy(&result); - -		if (ret.get_type() != Variant::ARRAY) { -			ERR_EXPLAIN("Wrong type for _get_property_list, must be an array of dictionaries."); -			ERR_FAIL(); -		} - -		Array arr = ret; -		for (int i = 0; i < arr.size(); i++) { -			Dictionary d = arr[i]; -			ERR_CONTINUE(!d.has("name")) -			ERR_CONTINUE(!d.has("type")) - -			PropertyInfo pinfo; - -			pinfo.type = Variant::Type(d["type"].operator int()); -			ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX); - -			pinfo.name = d["name"]; -			ERR_CONTINUE(pinfo.name == ""); - -			if (d.has("hint")) { -				pinfo.hint = PropertyHint(d["hint"].operator int()); -			} -			if (d.has("hint_string")) { -				pinfo.hint_string = d["hint_string"]; -			} -			if (d.has("usage")) { -				pinfo.usage = d["usage"]; -			} - -			p_properties->push_back(pinfo); -		} +	if (i == NUM_PLATFORMS) { +		ERR_EXPLAIN(String("No such platform: ") + p_platform); +		ERR_FAIL_V("");  	} -} -Variant::Type GDNativeInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { -	if (script->script_data->properties.has(p_name)) { -		*r_is_valid = true; -		return script->script_data->properties[p_name].info.type; -	} -	*r_is_valid = false; -	return Variant::NIL; +	return library_paths[i];  } -void GDNativeInstance::get_method_list(List<MethodInfo> *p_list) const { -	script->get_script_method_list(p_list); +String GDNativeLibrary::get_active_library_path() const { +	return library_paths[GDNativeLibrary::current_platform];  } -bool GDNativeInstance::has_method(const StringName &p_method) const { -	return script->has_method(p_method); +GDNative::GDNative() { +	initialized = false; +	native_handle = NULL;  } -Variant GDNativeInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { -	// TODO: validated methods & errors - -	GDNativeScriptData *data_ptr = script->script_data; -	while (data_ptr) { -		Map<StringName, GDNativeScriptData::Method>::Element *E = data_ptr->methods.find(p_method); -		if (E) { -			godot_variant result = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); -			return *(Variant *)&result; -		} -		data_ptr = data_ptr->base_data; -	} -	r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; -	return Variant(); +GDNative::~GDNative() { +	// TODO(karroffel): implement ALL the things!  } -void GDNativeInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { -	// TODO: validated methods & errors +extern "C" void _api_anchor(); -	GDNativeScriptData *data_ptr = script->script_data; -	while (data_ptr) { -		Map<StringName, GDNativeScriptData::Method>::Element *E = data_ptr->methods.find(p_method); -		if (E) { -			E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); -		} -		data_ptr = data_ptr->base_data; -	} +void GDNative::_compile_dummy_for_api() { +	_api_anchor();  } -void GDNativeInstance::_ml_call_reversed(GDNativeScriptData *data_ptr, const StringName &p_method, const Variant **p_args, int p_argcount) { -	// TODO: validated methods & errors +void GDNative::_bind_methods() { +	ClassDB::bind_method(D_METHOD("set_library", "library:GDNativeLibrary"), &GDNative::set_library); +	ClassDB::bind_method(D_METHOD("get_library:GDNativeLibrary"), &GDNative::get_library); -	if (data_ptr->base_data) -		_ml_call_reversed(data_ptr->base_data, p_method, p_args, p_argcount); +	ClassDB::bind_method(D_METHOD("initialize"), &GDNative::initialize); +	ClassDB::bind_method(D_METHOD("terminate"), &GDNative::terminate); -	// Variant::CallError ce; +	// TODO(karroffel): get_native_(raw_)call_types binding? -	Map<StringName, GDNativeScriptData::Method>::Element *E = data_ptr->methods.find(p_method); -	if (E) { -		E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); -	} -} - -void GDNativeInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { -	if (script.ptr() && script->script_data) { -		_ml_call_reversed(script->script_data, p_method, p_args, p_argcount); -	} -} +	// TODO(karroffel): make this a varargs function? +	ClassDB::bind_method(D_METHOD("call_native:Variant", "procedure_name", "arguments:Array"), &GDNative::call_native); -void GDNativeInstance::notification(int p_notification) { -	Variant value = p_notification; -	const Variant *args[1] = { &value }; -	call_multilevel(GDNativeScriptLanguage::singleton->strings._notification, args, 1); +	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library");  } -Ref<Script> GDNativeInstance::get_script() const { -	return script; +void GDNative::set_library(Ref<GDNativeLibrary> p_library) { +	library = p_library;  } -ScriptLanguage *GDNativeInstance::get_language() { -	return GDNativeScriptLanguage::singleton; +Ref<GDNativeLibrary> GDNative::get_library() { +	return library;  } -ScriptInstance::RPCMode GDNativeInstance::get_rpc_mode(const StringName &p_method) const { -	GDNativeScriptData::Method m = script->script_data->methods[p_method]; -	switch (m.rpc_mode) { -		case GODOT_METHOD_RPC_MODE_DISABLED: -			return RPC_MODE_DISABLED; -		case GODOT_METHOD_RPC_MODE_REMOTE: -			return RPC_MODE_REMOTE; -		case GODOT_METHOD_RPC_MODE_SYNC: -			return RPC_MODE_SYNC; -		case GODOT_METHOD_RPC_MODE_MASTER: -			return RPC_MODE_MASTER; -		case GODOT_METHOD_RPC_MODE_SLAVE: -			return RPC_MODE_SLAVE; -		default: -			return RPC_MODE_DISABLED; +bool GDNative::initialize() { +	if (library.is_null()) { +		ERR_PRINT("No library set, can't initialize GDNative object"); +		return false;  	} -} -ScriptInstance::RPCMode GDNativeInstance::get_rset_mode(const StringName &p_variable) const { -	GDNativeScriptData::Property p = script->script_data->properties[p_variable]; -	switch (p.rset_mode) { -		case GODOT_METHOD_RPC_MODE_DISABLED: -			return RPC_MODE_DISABLED; -		case GODOT_METHOD_RPC_MODE_REMOTE: -			return RPC_MODE_REMOTE; -		case GODOT_METHOD_RPC_MODE_SYNC: -			return RPC_MODE_SYNC; -		case GODOT_METHOD_RPC_MODE_MASTER: -			return RPC_MODE_MASTER; -		case GODOT_METHOD_RPC_MODE_SLAVE: -			return RPC_MODE_SLAVE; -		default: -			return RPC_MODE_DISABLED; +	String lib_path = library->get_active_library_path(); +	if (lib_path.empty()) { +		ERR_PRINT("No library set for this platform"); +		return false;  	} -} -GDNativeInstance::GDNativeInstance() { -	owner = NULL; -	userdata = NULL; -} - -GDNativeInstance::~GDNativeInstance() { -	if (script.is_valid()) { -		if (owner) { -			script->instances.erase(owner); -		} -		if (!script->script_data) -			return; -		script->script_data->destroy_func.destroy_func((godot_object *)owner, script->script_data->destroy_func.method_data, userdata); -		if (script->script_data->destroy_func.free_func) -			script->script_data->destroy_func.free_func(script->script_data->destroy_func.method_data); -		if (script->script_data->create_func.free_func) -			script->script_data->create_func.free_func(script->script_data->create_func.method_data); +	String path = ProjectSettings::get_singleton()->globalize_path(lib_path); +	Error err = OS::get_singleton()->open_dynamic_library(path, native_handle); +	if (err != OK) { +		return false;  	} -} - -// Language - -GDNativeScriptLanguage *GDNativeScriptLanguage::singleton = NULL; - -String GDNativeScriptLanguage::get_name() const { -	return "Native"; -} - -void _add_reload_node() { -#ifdef TOOLS_ENABLED -	GDNativeReloadNode *rn = memnew(GDNativeReloadNode); -	EditorNode::get_singleton()->add_child(rn); -#endif -} - -void GDNativeScriptLanguage::init() { -	// TODO: Expose globals -	GLOBAL_DEF("gdnative/default_gdnativelibrary", ""); -	PropertyInfo prop_info(Variant::STRING, "gdnative/default_gdnativelibrary", PROPERTY_HINT_FILE, "tres,res,dllib"); -	ProjectSettings::get_singleton()->set_custom_property_info("gdnative/default_gdnativelibrary", prop_info); - -// generate bindings -#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) - -	List<String> args = OS::get_singleton()->get_cmdline_args(); -	List<String>::Element *E = args.find("--gdnative-generate-json-api"); +	void *library_init; +	err = OS::get_singleton()->get_dynamic_library_symbol_handle( +			native_handle, +			init_symbol, +			library_init); -	if (E && E->next()) { -		if (generate_c_api(E->next()->get()) != OK) { -			ERR_PRINT("Failed to generate C API\n"); -		} +	if (err || !library_init) { +		return false;  	} -#endif -#ifdef TOOLS_ENABLED -	// if (SceneTree::get_singleton()->is_editor_hint()) { -	EditorNode::add_init_callback(&_add_reload_node); -// } -#endif -} - -String GDNativeScriptLanguage::get_type() const { -	return "Native"; -} - -String GDNativeScriptLanguage::get_extension() const { -	return "gdn"; -} - -Error GDNativeScriptLanguage::execute_file(const String &p_path) { -	return OK; // ?? -} - -void GDNativeScriptLanguage::finish() { -	// cleanup is for noobs -} - -// scons doesn't want to link in the api source so we need to call a dummy function to cause it to link -extern "C" void _api_anchor(); - -void GDNativeScriptLanguage::_compile_dummy_for_the_api() { -	_api_anchor(); -} +	godot_gdnative_init_fn library_init_fpointer; +	library_init_fpointer = (godot_gdnative_init_fn)library_init; -Ref<Script> GDNativeScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { -	GDNativeScript *src = memnew(GDNativeScript); -	src->set_script_name(p_class_name); -	return Ref<GDNativeScript>(src); -} +	godot_gdnative_init_options options; -bool GDNativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { -	return false; // TODO -} +	options.in_editor = SceneTree::get_singleton()->is_editor_hint(); +	options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); +	options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); +	options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE); -Script *GDNativeScriptLanguage::create_script() const { -	GDNativeScript *scr = memnew(GDNativeScript); -	return scr; -} +	library_init_fpointer(&options); -bool GDNativeScriptLanguage::has_named_classes() const {  	return true;  } -int GDNativeScriptLanguage::find_function(const String &p_function, const String &p_code) const { -	return -1; // No source code! -} - -String GDNativeScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { -	return ""; // No source code! -} - -void GDNativeScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { -	// TODO TODO TODO -} - -// TODO: Any debugging? (research) -String GDNativeScriptLanguage::debug_get_error() const { -	return ""; -} - -int GDNativeScriptLanguage::debug_get_stack_level_count() const { -	return 1; // ? -} - -int GDNativeScriptLanguage::debug_get_stack_level_line(int p_level) const { -	return -1; -} - -String GDNativeScriptLanguage::debug_get_stack_level_function(int p_level) const { -	return "[native code]"; // ? -} - -String GDNativeScriptLanguage::debug_get_stack_level_source(int p_level) const { -	return ""; -} - -void GDNativeScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} +bool GDNative::terminate() { -void GDNativeScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} - -String GDNativeScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { -	return ""; // ?? -} - -void GDNativeScriptLanguage::reload_all_scripts() { -	// @Todo -} +	if (native_handle == NULL) { +		ERR_PRINT("No valid library handle, can't terminate GDNative object"); +		return false; +	} -void GDNativeScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { -	// @Todo -	OS::get_singleton()->print("reload tool scripts\n"); -} +	Error error = OK; +	void *library_terminate; +	error = OS::get_singleton()->get_dynamic_library_symbol_handle( +			native_handle, +			terminate_symbol, +			library_terminate); +	if (error) { +		OS::get_singleton()->close_dynamic_library(native_handle); +		native_handle = NULL; +		return true; +	} -void GDNativeScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { -	p_extensions->push_back("gdn"); // Container file format -} +	godot_gdnative_terminate_fn library_terminate_pointer; +	library_terminate_pointer = (godot_gdnative_terminate_fn)library_terminate; -void GDNativeScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { -} +	// TODO(karroffel): remove this? Should be part of NativeScript, not +	// GDNative IMO +	godot_gdnative_terminate_options options; +	options.in_editor = SceneTree::get_singleton()->is_editor_hint(); -void GDNativeScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const { -} +	library_terminate_pointer(&options); -// TODO: all profilling -void GDNativeScriptLanguage::profiling_start() { -} +	// GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path); -void GDNativeScriptLanguage::profiling_stop() { -} +	OS::get_singleton()->close_dynamic_library(native_handle); +	native_handle = NULL; -int GDNativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { -	return 0; +	return false;  } -int GDNativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { -	return 0; +void GDNativeCallRegistry::register_native_call_type(StringName p_call_type, native_call_cb p_callback) { +	native_calls.insert(p_call_type, p_callback);  } -void GDNativeScriptLanguage::frame() { +void GDNativeCallRegistry::register_native_raw_call_type(StringName p_raw_call_type, native_raw_call_cb p_callback) { +	native_raw_calls.insert(p_raw_call_type, p_callback);  } -String GDNativeScriptLanguage::get_init_symbol_name() { -	return "godot_native_init"; // TODO: Maybe make some internal function which would do the actual stuff -} +Vector<StringName> GDNativeCallRegistry::get_native_call_types() { +	Vector<StringName> call_types; +	call_types.resize(native_calls.size()); -String GDNativeScriptLanguage::get_terminate_symbol_name() { -	return "godot_native_terminate"; -} +	size_t idx = 0; +	for (Map<StringName, native_call_cb>::Element *E = native_calls.front(); E; E = E->next(), idx++) { +		call_types[idx] = E->key(); +	} -GDNativeScriptLanguage::GDNativeScriptLanguage() { -	ERR_FAIL_COND(singleton); -	strings._notification = StringName("_notification"); -	singleton = this; -	initialized_libraries = Map<StringName, NativeLibrary *>(); +	return call_types;  } -GDNativeScriptLanguage::~GDNativeScriptLanguage() { -	singleton = NULL; -} +Vector<StringName> GDNativeCallRegistry::get_native_raw_call_types() { +	Vector<StringName> call_types; +	call_types.resize(native_raw_calls.size()); -// DLReloadNode +	size_t idx = 0; +	for (Map<StringName, native_raw_call_cb>::Element *E = native_raw_calls.front(); E; E = E->next(), idx++) { +		call_types[idx] = E->key(); +	} -void GDNativeReloadNode::_bind_methods() { -	ClassDB::bind_method("_notification", &GDNativeReloadNode::_notification); +	return call_types;  } -void GDNativeReloadNode::_notification(int p_what) { -#ifdef TOOLS_ENABLED - -	switch (p_what) { -		case MainLoop::NOTIFICATION_WM_FOCUS_IN: { - -			Set<NativeLibrary *> libs_to_reload; - -			for (Map<StringName, NativeLibrary *>::Element *L = GDNativeScriptLanguage::get_singleton()->initialized_libraries.front(); L; L = L->next()) { -				// check if file got modified at all -				// @Todo - -				libs_to_reload.insert(L->get()); -			} - -			for (Set<NativeLibrary *>::Element *L = libs_to_reload.front(); L; L = L->next()) { - -				GDNativeLibrary *lib = L->get()->dllib; - -				lib->_terminate(); -				lib->_initialize(); - -				// update placeholders (if any) - -				Set<GDNativeScript *> scripts; - -				for (Set<GDNativeScript *>::Element *S = GDNativeScriptLanguage::get_singleton()->script_list.front(); S; S = S->next()) { +Variant GDNative::call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments) { -					if (lib->native_library->scripts.has(S->get()->get_script_name())) { -						GDNativeScript *script = S->get(); -						script->script_data = lib->get_script_data(script->get_script_name()); -						scripts.insert(script); -					} -				} - -				for (Set<GDNativeScript *>::Element *S = scripts.front(); S; S = S->next()) { -					GDNativeScript *script = S->get(); -					if (script->placeholders.size() == 0) -						continue; - -					for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) { -						PlaceHolderScriptInstance *p = P->get(); -						script->_update_placeholder(p); -					} -				} -			} - -		} break; -		default: { -		}; +	Map<StringName, native_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_calls.find(p_native_call_type); +	if (!E) { +		ERR_PRINT((String("No handler for native call type \"" + p_native_call_type) + "\" found").utf8().get_data()); +		return Variant();  	} -#endif -} - -// Resource loader/saver - -RES ResourceFormatLoaderGDNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error) { -	ResourceFormatLoaderText rsflt; -	return rsflt.load(p_path, p_original_path, r_error); -} -void ResourceFormatLoaderGDNativeScript::get_recognized_extensions(List<String> *p_extensions) const { -	p_extensions->push_back("gdn"); -} -bool ResourceFormatLoaderGDNativeScript::handles_type(const String &p_type) const { -	return (p_type == "Script" || p_type == "Native"); -} -String ResourceFormatLoaderGDNativeScript::get_resource_type(const String &p_path) const { -	String el = p_path.get_extension().to_lower(); -	if (el == "gdn") -		return "Native"; -	return ""; -} +	String procedure_name = p_procedure_name; +	godot_variant result = E->get()(native_handle, (godot_string *)&procedure_name, (godot_array *)&p_arguments); -Error ResourceFormatSaverGDNativeScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { -	ResourceFormatSaverText rfst; -	return rfst.save(p_path, p_resource, p_flags); +	return *(Variant *)&result;  } -bool ResourceFormatSaverGDNativeScript::recognize(const RES &p_resource) const { -	return p_resource->cast_to<GDNativeScript>() != NULL; -} +void GDNative::call_native_raw(StringName p_raw_call_type, StringName p_procedure_name, void *data, int num_args, void **args, void *r_return) { -void ResourceFormatSaverGDNativeScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { -	if (p_resource->cast_to<GDNativeScript>()) { -		p_extensions->push_back("gdn"); +	Map<StringName, native_raw_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_raw_calls.find(p_raw_call_type); +	if (!E) { +		ERR_PRINT((String("No handler for native raw call type \"" + p_raw_call_type) + "\" found").utf8().get_data()); +		return;  	} + +	String procedure_name = p_procedure_name; +	E->get()(native_handle, (godot_string *)&procedure_name, data, num_args, args, r_return);  } diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 650f999192..dd845cab7a 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -34,382 +34,112 @@  #include "io/resource_saver.h"  #include "os/thread_safe.h"  #include "resource.h" -#include "scene/main/node.h" -#include "script_language.h" -#include "self_list.h" -#include "godot.h" +#include "godot/gdnative.h" -struct GDNativeScriptData; -class GDNativeLibrary; - -struct NativeLibrary { -	StringName path; -	void *handle; - -	GDNativeLibrary *dllib; - -	Map<StringName, GDNativeScriptData *> scripts; - -	static Error initialize(NativeLibrary *&p_native_lib, const StringName p_path); -	static Error terminate(NativeLibrary *&p_native_lib); -}; - -struct GDNativeScriptData { -	/* typedef void* (InstanceFunc)(godot_object* instance); -	typedef void (DestroyFunc)(godot_object* instance,void* userdata); -	typedef godot_variant (MethodFunc)(godot_object *instance, void *userdata, void *method_data, int arg_count,godot_variant **args); -	typedef void (MethodDataFreeFunc)(void *method_data); -	typedef void (SetterFunc)(godot_object* instance,void* userdata,godot_variant value); -	typedef godot_variant (GetterFunc)(godot_object* instance,void* userdata);*/ - -	struct Method { -		godot_instance_method method; -		MethodInfo info; -		int rpc_mode; - -		Method() { -		} -		Method(godot_instance_method p_method, MethodInfo p_info, int p_rpc_mode) { -			method = p_method; -			info = p_info; -			rpc_mode = p_rpc_mode; -		} -	}; -	struct Property { -		godot_property_set_func setter; -		godot_property_get_func getter; -		PropertyInfo info; -		Variant default_value; -		int rset_mode; - -		Property() { -		} -		Property(godot_property_set_func p_setter, godot_property_get_func p_getter) { -			setter = p_setter; -			getter = p_getter; -		} -		Property(godot_property_set_func p_setter, godot_property_get_func p_getter, PropertyInfo p_info, Variant p_default_value, int p_rset_mode) { -			setter = p_setter; -			getter = p_getter; -			info = p_info; -			default_value = p_default_value; -			rset_mode = p_rset_mode; -		} -	}; - -	struct Signal { -		MethodInfo signal; -	}; - -	Map<StringName, Method> methods; -	Map<StringName, Property> properties; -	Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals -	StringName base; -	StringName base_native_type; -	GDNativeScriptData *base_data; -	godot_instance_create_func create_func; -	godot_instance_destroy_func destroy_func; - -	bool is_tool; - -	GDNativeScriptData() { -		base = StringName(); -		base_data = NULL; -		is_tool = false; -	} -	GDNativeScriptData(StringName p_base, godot_instance_create_func p_instance, godot_instance_destroy_func p_free) { -		base = p_base; -		base_data = NULL; -		create_func = p_instance; -		destroy_func = p_free; -		is_tool = false; -	} -}; - -class GDNativeScript : public Script { -	GDCLASS(GDNativeScript, Script); - -	Ref<GDNativeLibrary> library; -	StringName script_name; -	StringName base_native_type; -	Set<Object *> instances; -	GDNativeScriptData *script_data; - -#ifdef TOOLS_ENABLED -	Set<PlaceHolderScriptInstance *> placeholders; -	void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); -	virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); -#endif - -	friend class GDNativeInstance; -	friend class GDNativeScriptLanguage; -	friend class GDNativeReloadNode; -	friend class GDNativeLibrary; - -protected: -	static void _bind_methods(); - -public: -	virtual bool can_instance() const; - -	virtual Ref<Script> get_base_script() const; //for script inheritance - -	virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so -	virtual ScriptInstance *instance_create(Object *p_this); -	virtual bool instance_has(const Object *p_this) const; - -	virtual bool has_source_code() const; -	virtual String get_source_code() const; -	virtual void set_source_code(const String &p_code) {} -	virtual Error reload(bool p_keep_state = false); - -	virtual bool has_method(const StringName &p_method) const; -	virtual MethodInfo get_method_info(const StringName &p_method) const; - -	virtual bool is_tool() const; - -	virtual String get_node_type() const; +class GDNativeLibrary : public Resource { +	GDCLASS(GDNativeLibrary, Resource) -	virtual ScriptLanguage *get_language() const; +	enum Platform { +		X11_32BIT, +		X11_64BIT, +		WINDOWS_32BIT, +		WINDOWS_64BIT, +		// NOTE(karroffel): I heard OSX 32 bit is dead, so 64 only +		OSX, -	virtual bool has_script_signal(const StringName &p_signal) const; -	virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; +		// TODO(karroffel): all different android versions and archs +		ANDROID, -	virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const; +		// TODO(karroffe): all different iOS versions and archs +		IOS, -	virtual void update_exports() {} //editor tool -	virtual void get_script_method_list(List<MethodInfo> *p_list) const; -	virtual void get_script_property_list(List<PropertyInfo> *p_list) const; +		// TODO(karroffel): figure out how to deal with web stuff at all... +		WASM, -	Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error); +		// TODO(karroffel): does UWP have different libs?? +		// UWP, -	Ref<GDNativeLibrary> get_library() const; -	void set_library(Ref<GDNativeLibrary> p_library); +		NUM_PLATFORMS -	StringName get_script_name() const; -	void set_script_name(StringName p_script_name); +	}; -	GDNativeScript(); -	~GDNativeScript(); -}; +	static String platform_names[NUM_PLATFORMS]; +	static String platform_lib_ext[NUM_PLATFORMS]; -class GDNativeLibrary : public Resource { -	_THREAD_SAFE_CLASS_ +	// TODO(karroffel): make this actually do something lol. +	static Platform current_platform; -	GDCLASS(GDNativeLibrary, Resource); -	OBJ_SAVE_TYPE(GDNativeLibrary); - -	Map<StringName, String> platform_files; -	NativeLibrary *native_library; -	static GDNativeLibrary *currently_initialized_library; +	String library_paths[NUM_PLATFORMS];  protected: -	friend class GDNativeScript; -	friend struct NativeLibrary; -	friend class GDNativeReloadNode; - -	GDNativeScriptData *get_script_data(const StringName p_name); -  	bool _set(const StringName &p_name, const Variant &p_value);  	bool _get(const StringName &p_name, Variant &r_ret) const;  	void _get_property_list(List<PropertyInfo> *p_list) const; -	void _notification(int p_what); -	static void _bind_methods();  public: -	Error _initialize(); -	Error _terminate(); - -	static GDNativeLibrary *get_currently_initialized_library(); - -	void _register_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func); -	void _register_tool_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func); -	void _register_script_method(const StringName p_name, const StringName p_method, godot_method_attributes p_attr, godot_instance_method p_func, MethodInfo p_info); -	void _register_script_property(const StringName p_name, const String p_path, godot_property_attributes *p_attr, godot_property_set_func p_setter, godot_property_get_func p_getter); -	void _register_script_signal(const StringName p_name, const godot_signal *p_signal); - -	void set_platform_file(StringName p_platform, String p_file); -	String get_platform_file(StringName p_platform) const; -  	GDNativeLibrary();  	~GDNativeLibrary(); -}; - -class GDNativeInstance : public ScriptInstance { -	friend class GDNativeScript; -	Object *owner; -	Ref<GDNativeScript> script; -	void *userdata; - -	void _ml_call_reversed(GDNativeScriptData *data_ptr, const StringName &p_method, const Variant **p_args, int p_argcount); - -public: -	_FORCE_INLINE_ Object *get_owner() { return owner; } - -	_FORCE_INLINE_ void *get_userdata() { return userdata; } - -	virtual bool set(const StringName &p_name, const Variant &p_value); -	virtual bool get(const StringName &p_name, Variant &r_ret) const; -	virtual void get_property_list(List<PropertyInfo> *p_properties) const; -	virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; - -	virtual void get_method_list(List<MethodInfo> *p_list) const; -	virtual bool has_method(const StringName &p_method) const; -	virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); -	virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); -	virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); - -	Variant debug_get_member_by_index(int p_idx) const { return Variant(); } - -	virtual void notification(int p_notification); - -	virtual Ref<Script> get_script() const; - -	virtual ScriptLanguage *get_language(); - -	void set_path(const String &p_path); - -	void reload_members(); +	static void _bind_methods(); -	virtual RPCMode get_rpc_mode(const StringName &p_method) const; -	virtual RPCMode get_rset_mode(const StringName &p_variable) const; +	void set_library_path(StringName p_platform, String p_path); +	String get_library_path(StringName p_platform) const; -	GDNativeInstance(); -	~GDNativeInstance(); +	String get_active_library_path() const;  }; -class GDNativeReloadNode; +typedef godot_variant (*native_call_cb)(void *, godot_string *, godot_array *); +typedef void (*native_raw_call_cb)(void *, godot_string *, void *, int, void **, void *); -class GDNativeScriptLanguage : public ScriptLanguage { -	friend class GDNativeScript; -	friend class GDNativeInstance; -	friend class GDNativeReloadNode; -	friend class GDNativeLibrary; +struct GDNativeCallRegistry { +	static GDNativeCallRegistry *singleton; -	static GDNativeScriptLanguage *singleton; +	inline GDNativeCallRegistry *get_singleton() { +		return singleton; +	} -	Variant *_global_array; // @Unused necessary? -	Vector<Variant> global_array; // @Unused necessary? -	Map<StringName, int> globals; // @Unused necessary? +	inline GDNativeCallRegistry() +		: native_calls(), +		  native_raw_calls() {} -	// @Unused necessary? -	void _add_global(const StringName &p_name, const Variant &p_value); +	Map<StringName, native_call_cb> native_calls; +	Map<StringName, native_raw_call_cb> native_raw_calls; -	Mutex *lock; +	void register_native_call_type(StringName p_call_type, native_call_cb p_callback); +	void register_native_raw_call_type(StringName p_raw_call_type, native_raw_call_cb p_callback); -	Set<GDNativeScript *> script_list; +	Vector<StringName> get_native_call_types(); +	Vector<StringName> get_native_raw_call_types(); +}; -	bool profiling; -	uint64_t script_frame_time; +class GDNative : public Reference { +	GDCLASS(GDNative, Reference) -	struct { +	Ref<GDNativeLibrary> library; +	bool initialized; -		StringName _notification; +	// TODO(karroffel): different platforms? WASM???? +	void *native_handle; -	} strings; +	void _compile_dummy_for_api();  public: -	Map<StringName, NativeLibrary *> initialized_libraries; - -	_FORCE_INLINE_ static GDNativeScriptLanguage *get_singleton() { return singleton; } - -	virtual String get_name() const; - -	/* LANGUAGE FUNCTIONS */ -	virtual void init(); -	virtual String get_type() const; -	virtual String get_extension() const; -	virtual Error execute_file(const String &p_path); -	virtual void finish(); - -	/* EDITOR FUNCTIONS */ - -	virtual void get_reserved_words(List<String> *p_words) const {}; -	virtual void get_comment_delimiters(List<String> *p_delimiters) const {}; -	virtual void get_string_delimiters(List<String> *p_delimiters) const {}; -	virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; -	virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const; -	virtual Script *create_script() const; -	virtual bool has_named_classes() const; -	virtual int find_function(const String &p_function, const String &p_code) const; -	virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; -	virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } -	virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; } - -	virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } +	GDNative(); +	~GDNative(); -	virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {}; -	virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); - -	/* MULTITHREAD FUNCTIONS */ - -	//some VMs need to be notified of thread creation/exiting to allocate a stack -	virtual void thread_enter() {} -	virtual void thread_exit() {} - -	/* DEBUGGER FUNCTIONS */ - -	virtual String debug_get_error() const; -	virtual int debug_get_stack_level_count() const; -	virtual int debug_get_stack_level_line(int p_level) const; -	virtual String debug_get_stack_level_function(int p_level) const; -	virtual String debug_get_stack_level_source(int p_level) const; -	virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1){}; -	virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); -	virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); -	virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1); - -	virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } - -	virtual void reload_all_scripts(); -	virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload); -	/* LOADER FUNCTIONS */ - -	virtual void get_recognized_extensions(List<String> *p_extensions) const; -	virtual void get_public_functions(List<MethodInfo> *p_functions) const; -	virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const; - -	/* PROFILLER FUNCTIONS */ - -	virtual void profiling_start(); -	virtual void profiling_stop(); - -	virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); -	virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); - -	virtual void frame(); - -	static String get_init_symbol_name(); -	static String get_terminate_symbol_name(); - -	/* HACKER FUNCTIONS */ -	void _compile_dummy_for_the_api(); +	static void _bind_methods(); -	GDNativeScriptLanguage(); -	~GDNativeScriptLanguage(); -}; +	void set_library(Ref<GDNativeLibrary> p_library); +	Ref<GDNativeLibrary> get_library(); -class GDNativeReloadNode : public Node { -	GDCLASS(GDNativeReloadNode, Node) -public: -	static void _bind_methods(); -	void _notification(int p_what); -}; +	bool is_initialized(); -class ResourceFormatLoaderGDNativeScript : public ResourceFormatLoader { -public: -	virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); -	virtual void get_recognized_extensions(List<String> *p_extensions) const; -	virtual bool handles_type(const String &p_type) const; -	virtual String get_resource_type(const String &p_path) const; -}; +	bool initialize(); +	bool terminate(); -class ResourceFormatSaverGDNativeScript : public ResourceFormatSaver { -	virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); -	virtual bool recognize(const RES &p_resource) const; -	virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; +	Variant call_native(StringName p_call_type, StringName p_procedure_name, Array p_arguments = Array()); +	void call_native_raw(StringName p_raw_call_type, StringName p_procedure_name, void *data, int num_args, void **args, void *r_return);  };  #endif // GDNATIVE_H diff --git a/modules/gdnative/godot/godot_array.cpp b/modules/gdnative/godot/array.cpp index 5497dde520..c068eecf8f 100644 --- a/modules/gdnative/godot/godot_array.cpp +++ b/modules/gdnative/godot/array.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_array.cpp                                                      */ +/*  array.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_array.h" +#include "array.h"  #include "core/array.h"  #include "core/os/memory.h" diff --git a/modules/gdnative/godot/godot_array.h b/modules/gdnative/godot/array.h index bf8bc61977..cbdbfbdde3 100644 --- a/modules/gdnative/godot/godot_array.h +++ b/modules/gdnative/godot/array.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_array.h                                                        */ +/*  array.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -37,16 +37,19 @@ extern "C" {  #include <stdint.h> +#define GODOT_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED -typedef struct godot_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_ARRAY_SIZE];  } godot_array;  #endif -#include "godot_pool_arrays.h" -#include "godot_variant.h" +#include "pool_arrays.h" +#include "variant.h" -#include "../godot.h" +#include "gdnative.h"  void GDAPI godot_array_new(godot_array *r_dest);  void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src); diff --git a/modules/gdnative/godot/godot_basis.cpp b/modules/gdnative/godot/basis.cpp index 46464932c5..7188215d04 100644 --- a/modules/gdnative/godot/godot_basis.cpp +++ b/modules/gdnative/godot/basis.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_basis.cpp                                                      */ +/*  basis.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_basis.h" +#include "basis.h"  #include "core/variant.h"  #include "core/math/matrix3.h" diff --git a/modules/gdnative/godot/godot_basis.h b/modules/gdnative/godot/basis.h index a096a8cc08..79b2b45fdd 100644 --- a/modules/gdnative/godot/godot_basis.h +++ b/modules/gdnative/godot/basis.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_basis.h                                                        */ +/*  basis.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,18 @@ extern "C" {  #include <stdint.h> +#define GODOT_BASIS_SIZE 36 +  #ifndef GODOT_CORE_API_GODOT_BASIS_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_BASIS_TYPE_DEFINED -typedef struct godot_basis { -	uint8_t _dont_touch_that[36]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_BASIS_SIZE];  } godot_basis;  #endif -#include "../godot.h" -#include "godot_vector3.h" +#include "gdnative.h" +#include "quat.h" +#include "vector3.h"  void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis);  void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi); diff --git a/modules/gdnative/godot/godot_color.cpp b/modules/gdnative/godot/color.cpp index 6dedf2ab10..eac966ca1f 100644 --- a/modules/gdnative/godot/godot_color.cpp +++ b/modules/gdnative/godot/color.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_color.cpp                                                      */ +/*  color.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_color.h" +#include "color.h"  #include "core/variant.h"  #include "core/color.h" diff --git a/modules/gdnative/godot/godot_color.h b/modules/gdnative/godot/color.h index 10dc228b1c..77e709fbe3 100644 --- a/modules/gdnative/godot/godot_color.h +++ b/modules/gdnative/godot/color.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_color.h                                                        */ +/*  color.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,17 @@ extern "C" {  #include <stdint.h> +#define GODOT_COLOR_SIZE 16 +  #ifndef GODOT_CORE_API_GODOT_COLOR_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_COLOR_TYPE_DEFINED -typedef struct godot_color { -	uint8_t _dont_touch_that[16]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_COLOR_SIZE];  } godot_color;  #endif -#include "../godot.h" -#include "godot_string.h" +#include "gdnative.h" +#include "string.h"  void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a);  void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b); diff --git a/modules/gdnative/godot/godot_dictionary.cpp b/modules/gdnative/godot/dictionary.cpp index a14a86248b..1c0761edfd 100644 --- a/modules/gdnative/godot/godot_dictionary.cpp +++ b/modules/gdnative/godot/dictionary.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_dictionary.cpp                                                 */ +/*  dictionary.cpp                                                       */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_dictionary.h" +#include "dictionary.h"  #include "core/variant.h"  #include "core/dictionary.h" diff --git a/modules/gdnative/godot/godot_dictionary.h b/modules/gdnative/godot/dictionary.h index 4ded0d38da..a08deb27df 100644 --- a/modules/gdnative/godot/godot_dictionary.h +++ b/modules/gdnative/godot/dictionary.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_dictionary.h                                                   */ +/*  dictionary.h                                                         */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,16 +36,18 @@ extern "C" {  #include <stdint.h> +#define GODOT_DICTIONARY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED -typedef struct godot_dictionary { -	uint8_t _dont_touch_that[8]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_DICTIONARY_SIZE];  } godot_dictionary;  #endif -#include "../godot.h" -#include "godot_array.h" -#include "godot_variant.h" +#include "array.h" +#include "gdnative.h" +#include "variant.h"  void GDAPI godot_dictionary_new(godot_dictionary *r_dest);  void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src); diff --git a/modules/gdnative/godot.cpp b/modules/gdnative/godot/gdnative.cpp index 764ce7c3ea..7b94b75a52 100644 --- a/modules/gdnative/godot.cpp +++ b/modules/gdnative/godot/gdnative.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot.cpp                                                            */ +/*  gdnative.cpp                                                         */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot.h" +#include "gdnative.h"  #include "class_db.h"  #include "error_macros.h" @@ -79,13 +79,6 @@ void _api_anchor() {  	_variant_api_anchor();  } -extern "C++" { -template <class a, class b> -_FORCE_INLINE_ a memcast(b v) { -	return *((a *)&v); -} -} -  void GDAPI godot_object_destroy(godot_object *p_o) {  	memdelete((Object *)p_o);  } @@ -142,65 +135,6 @@ void GDAPI godot_method_bind_varcall(godot_method_bind *p_method_bind)  }  */ -// Script API - -void GDAPI godot_script_register_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { -	GDNativeLibrary *library = GDNativeLibrary::get_currently_initialized_library(); -	if (!library) { -		ERR_EXPLAIN("Attempt to register script after initializing library!"); -		ERR_FAIL(); -	} -	library->_register_script(p_name, p_base, p_create_func, p_destroy_func); -} - -void GDAPI godot_script_register_tool_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { -	GDNativeLibrary *library = GDNativeLibrary::get_currently_initialized_library(); -	if (!library) { -		ERR_EXPLAIN("Attempt to register script after initializing library!"); -		ERR_FAIL(); -	} -	library->_register_tool_script(p_name, p_base, p_create_func, p_destroy_func); -} - -void GDAPI godot_script_register_method(const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) { -	GDNativeLibrary *library = GDNativeLibrary::get_currently_initialized_library(); -	if (!library) { -		ERR_EXPLAIN("Attempt to register script after initializing library!"); -		ERR_FAIL(); -	} -	library->_register_script_method(p_name, p_function_name, p_attr, p_method, MethodInfo()); -} - -void GDAPI godot_script_register_property(const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) { -	GDNativeLibrary *library = GDNativeLibrary::get_currently_initialized_library(); -	if (!library) { -		ERR_EXPLAIN("Attempt to register script after initializing library!"); -		ERR_FAIL(); -	} - -	library->_register_script_property(p_name, p_path, p_attr, p_set_func, p_get_func); -} - -void GDAPI godot_script_register_signal(const char *p_name, const godot_signal *p_signal) { -	GDNativeLibrary *library = GDNativeLibrary::get_currently_initialized_library(); -	if (!library) { -		ERR_EXPLAIN("Attempt to register script after initializing library!"); -		ERR_FAIL(); -	} - -	library->_register_script_signal(p_name, p_signal); -} - -void GDAPI *godot_native_get_userdata(godot_object *p_instance) { -	Object *instance = (Object *)p_instance; -	if (!instance) -		return NULL; -	if (instance->get_script_instance() && instance->get_script_instance()->get_language() == GDNativeScriptLanguage::get_singleton()) { -		return ((GDNativeInstance *)instance->get_script_instance())->get_userdata(); -	} -	return NULL; -} -  godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname) {  	ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));  	if (class_info) diff --git a/modules/gdnative/godot/gdnative.h b/modules/gdnative/godot/gdnative.h new file mode 100644 index 0000000000..4b79706b52 --- /dev/null +++ b/modules/gdnative/godot/gdnative.h @@ -0,0 +1,298 @@ +/*************************************************************************/ +/*  gdnative.h                                                           */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +#ifndef GODOT_GDNATIVE_H +#define GODOT_GDNATIVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef GDAPI_BUILT_IN +#define GDAPI_EXPORT +#endif + +#ifdef _WIN32 +#if defined(GDAPI_EXPORT) +#define GDCALLINGCONV +#define GDAPI __declspec(dllexport) GDCALLINGCONV +#else +#define GDCALLINGCONV +#define GDAPI __declspec(dllimport) GDCALLINGCONV +#endif +#elif defined(__APPLE__) +#include "TargetConditionals.h" +#if TARGET_OS_IPHONE +#define GDCALLINGCONV +#define GDAPI +#elif TARGET_OS_MAC +#define GDCALLINGCONV __attribute__((sysv_abi)) +#define GDAPI GDCALLINGCONV +#endif +#else +#define GDCALLINGCONV __attribute__((sysv_abi)) +#define GDAPI GDCALLINGCONV +#endif + +// This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!! +#ifdef _WIN32 +#define GDN_EXPORT __declspec(dllexport) +#else +#define GDN_EXPORT +#endif + +#include <stdbool.h> +#include <stdint.h> + +#define GODOT_API_VERSION 1 + +////// Error + +typedef enum { +	GODOT_OK, +	GODOT_FAILED, ///< Generic fail error +	GODOT_ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable +	GODOT_ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet +	GODOT_ERR_UNAUTHORIZED, ///< Missing credentials for requested resource +	GODOT_ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5) +	GODOT_ERR_OUT_OF_MEMORY, ///< Out of memory +	GODOT_ERR_FILE_NOT_FOUND, +	GODOT_ERR_FILE_BAD_DRIVE, +	GODOT_ERR_FILE_BAD_PATH, +	GODOT_ERR_FILE_NO_PERMISSION, // (10) +	GODOT_ERR_FILE_ALREADY_IN_USE, +	GODOT_ERR_FILE_CANT_OPEN, +	GODOT_ERR_FILE_CANT_WRITE, +	GODOT_ERR_FILE_CANT_READ, +	GODOT_ERR_FILE_UNRECOGNIZED, // (15) +	GODOT_ERR_FILE_CORRUPT, +	GODOT_ERR_FILE_MISSING_DEPENDENCIES, +	GODOT_ERR_FILE_EOF, +	GODOT_ERR_CANT_OPEN, ///< Can't open a resource/socket/file +	GODOT_ERR_CANT_CREATE, // (20) +	GODOT_ERR_QUERY_FAILED, +	GODOT_ERR_ALREADY_IN_USE, +	GODOT_ERR_LOCKED, ///< resource is locked +	GODOT_ERR_TIMEOUT, +	GODOT_ERR_CANT_CONNECT, // (25) +	GODOT_ERR_CANT_RESOLVE, +	GODOT_ERR_CONNECTION_ERROR, +	GODOT_ERR_CANT_AQUIRE_RESOURCE, +	GODOT_ERR_CANT_FORK, +	GODOT_ERR_INVALID_DATA, ///< Data passed is invalid	(30) +	GODOT_ERR_INVALID_PARAMETER, ///< Parameter passed is invalid +	GODOT_ERR_ALREADY_EXISTS, ///< When adding, item already exists +	GODOT_ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist +	GODOT_ERR_DATABASE_CANT_READ, ///< database is full +	GODOT_ERR_DATABASE_CANT_WRITE, ///< database is full	(35) +	GODOT_ERR_COMPILATION_FAILED, +	GODOT_ERR_METHOD_NOT_FOUND, +	GODOT_ERR_LINK_FAILED, +	GODOT_ERR_SCRIPT_FAILED, +	GODOT_ERR_CYCLIC_LINK, // (40) +	GODOT_ERR_INVALID_DECLARATION, +	GODOT_ERR_DUPLICATE_SYMBOL, +	GODOT_ERR_PARSE_ERROR, +	GODOT_ERR_BUSY, +	GODOT_ERR_SKIP, // (45) +	GODOT_ERR_HELP, ///< user requested help!! +	GODOT_ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior. +	GODOT_ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames +	GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though +	GODOT_ERR_WTF = GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above +} godot_error; + +////// bool + +typedef bool godot_bool; + +#define GODOT_TRUE 1 +#define GODOT_FALSE 0 + +/////// int + +typedef int godot_int; + +/////// real + +typedef float godot_real; + +/////// Object (forward declared) +typedef void godot_object; + +/////// Brute force forward declarations for the rest +/* +typedef struct godot_variant godot_variant; +typedef struct godot_string godot_string; +typedef struct godot_vector2 godot_vector2; +typedef struct godot_rect2 godot_rect2; +typedef struct godot_vector3 godot_vector3; +typedef struct godot_transform2d godot_transform2d; +typedef struct godot_plane godot_plane; +typedef struct godot_quat godot_quat; +typedef struct godot_rect3 godot_rect3; +typedef struct godot_basis godot_basis; +typedef struct godot_transform godot_transform; +typedef struct godot_color godot_color; +typedef struct godot_node_path godot_node_path; +typedef struct godot_rid godot_rid; +typedef struct godot_dictionary godot_dictionary; +typedef struct godot_array godot_array; +typedef struct godot_pool_byte_array godot_pool_byte_array; +typedef struct godot_pool_int_array godot_pool_int_array; +typedef struct godot_pool_real_array godot_pool_real_array; +typedef struct godot_pool_string_array godot_pool_string_array; +typedef struct godot_pool_vector2_array godot_pool_vector2_array; +typedef struct godot_pool_vector3_array godot_pool_vector3_array; +typedef struct godot_pool_color_array godot_pool_color_array; +*/ +/////// String + +#include "string.h" + +////// Vector2 + +#include "vector2.h" + +////// Rect2 + +#include "rect2.h" + +////// Vector3 + +#include "vector3.h" + +////// Transform2D + +#include "transform2d.h" + +/////// Plane + +#include "plane.h" + +/////// Quat + +#include "quat.h" + +/////// Rect3 + +#include "rect3.h" + +/////// Basis + +#include "basis.h" + +/////// Transform + +#include "transform.h" + +/////// Color + +#include "color.h" + +/////// NodePath + +#include "node_path.h" + +/////// RID + +#include "rid.h" + +/////// Dictionary + +#include "dictionary.h" + +/////// Array + +#include "array.h" + +// single API file for Pool*Array +#include "pool_arrays.h" + +void GDAPI godot_object_destroy(godot_object *p_o); + +////// Variant + +#include "variant.h" + +////// Singleton API + +godot_object GDAPI *godot_global_get_singleton(char *p_name); // result shouldn't be freed + +////// MethodBind API + +typedef struct { +	uint8_t _dont_touch_that[1]; // TODO +} godot_method_bind; + +godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname); +void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret); +godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error); +////// Script API + +typedef struct { +	godot_bool in_editor; +	uint64_t core_api_hash; +	uint64_t editor_api_hash; +	uint64_t no_api_hash; +} godot_gdnative_init_options; + +typedef struct { +	godot_bool in_editor; +} godot_gdnative_terminate_options; + +// Calling convention? +typedef godot_object *(*godot_class_constructor)(); + +godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname); + +godot_dictionary GDAPI godot_get_global_constants(); + +////// GDNative procedure types +typedef void (*godot_gdnative_init_fn)(godot_gdnative_init_options *); +typedef void (*godot_gdnative_terminate_fn)(godot_gdnative_terminate_options *); +typedef godot_variant (*godot_gdnative_procedure_fn)(void *, godot_array *); + +////// System Functions + +//using these will help Godot track how much memory is in use in debug mode +void GDAPI *godot_alloc(int p_bytes); +void GDAPI *godot_realloc(void *p_ptr, int p_bytes); +void GDAPI godot_free(void *p_ptr); + +//print using Godot's error handler list +void GDAPI godot_print_error(const char *p_description, const char *p_function, const char *p_file, int p_line); +void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line); +void GDAPI godot_print(const godot_string *p_message); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_C_H diff --git a/modules/gdnative/godot/icon.png.import b/modules/gdnative/godot/icon.png.import new file mode 100644 index 0000000000..27920124f9 --- /dev/null +++ b/modules/gdnative/godot/icon.png.import @@ -0,0 +1,23 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-aa47d037a37fb38b3b7e7828e4eec407.stex" + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +stream=false +size_limit=0 +detect_3d=true diff --git a/modules/gdnative/godot/godot_node_path.cpp b/modules/gdnative/godot/node_path.cpp index c8eacd05af..a9edbc8352 100644 --- a/modules/gdnative/godot/godot_node_path.cpp +++ b/modules/gdnative/godot/node_path.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_node_path.cpp                                                  */ +/*  node_path.cpp                                                        */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_node_path.h" +#include "node_path.h"  #include "core/variant.h"  #include "core/path_db.h" diff --git a/modules/gdnative/godot/godot_node_path.h b/modules/gdnative/godot/node_path.h index b0c9d44859..06955a052e 100644 --- a/modules/gdnative/godot/godot_node_path.h +++ b/modules/gdnative/godot/node_path.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_node_path.h                                                    */ +/*  node_path.h                                                          */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,17 @@ extern "C" {  #include <stdint.h> +#define GODOT_NODE_PATH_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED -typedef struct godot_node_path { -	uint8_t _dont_touch_that[8]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_NODE_PATH_SIZE];  } godot_node_path;  #endif -#include "../godot.h" -#include "godot_string.h" +#include "gdnative.h" +#include "string.h"  void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from);  void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src); diff --git a/modules/gdnative/godot/godot_plane.cpp b/modules/gdnative/godot/plane.cpp index 68adbd4a98..e9e659e5da 100644 --- a/modules/gdnative/godot/godot_plane.cpp +++ b/modules/gdnative/godot/plane.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_plane.cpp                                                      */ +/*  plane.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_plane.h" +#include "plane.h"  #include "core/variant.h"  #include "core/math/plane.h" diff --git a/modules/gdnative/godot/godot_plane.h b/modules/gdnative/godot/plane.h index cfc955f277..e9e3b71e03 100644 --- a/modules/gdnative/godot/godot_plane.h +++ b/modules/gdnative/godot/plane.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_plane.h                                                        */ +/*  plane.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,17 @@ extern "C" {  #include <stdint.h> +#define GODOT_PLANE_SIZE 16 +  #ifndef GODOT_CORE_API_GODOT_PLANE_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_PLANE_TYPE_DEFINED -typedef struct godot_plane { -	uint8_t _dont_touch_that[16]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_PLANE_SIZE];  } godot_plane;  #endif -#include "../godot.h" -#include "godot_vector3.h" +#include "gdnative.h" +#include "vector3.h"  void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d);  void GDAPI godot_plane_new_with_vectors(godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3); diff --git a/modules/gdnative/godot/godot_pool_arrays.cpp b/modules/gdnative/godot/pool_arrays.cpp index ea9aceea81..6a6ee0f126 100644 --- a/modules/gdnative/godot/godot_pool_arrays.cpp +++ b/modules/gdnative/godot/pool_arrays.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_pool_arrays.cpp                                                */ +/*  pool_arrays.cpp                                                      */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,11 +27,15 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_pool_arrays.h" +#include "pool_arrays.h"  #include "array.h" +#include "core/variant.h"  #include "dvector.h" -#include "variant.h" + +#include "core/color.h" +#include "core/math/math_2d.h" +#include "core/math/vector3.h"  #ifdef __cplusplus  extern "C" { diff --git a/modules/gdnative/godot/godot_pool_arrays.h b/modules/gdnative/godot/pool_arrays.h index a794d03f01..1e2916cea9 100644 --- a/modules/gdnative/godot/godot_pool_arrays.h +++ b/modules/gdnative/godot/pool_arrays.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_pool_arrays.h                                                  */ +/*  pool_arrays.h                                                        */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -38,66 +38,87 @@ extern "C" {  /////// PoolByteArray +#define GODOT_POOL_BYTE_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED -typedef struct godot_pool_byte_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_BYTE_ARRAY_SIZE];  } godot_pool_byte_array;  #endif  /////// PoolIntArray +#define GODOT_POOL_INT_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED -typedef struct godot_pool_int_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_INT_ARRAY_SIZE];  } godot_pool_int_array;  #endif  /////// PoolRealArray +#define GODOT_POOL_REAL_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED -typedef struct godot_pool_real_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_REAL_ARRAY_SIZE];  } godot_pool_real_array;  #endif  /////// PoolStringArray +#define GODOT_POOL_STRING_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED -typedef struct godot_pool_string_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_STRING_ARRAY_SIZE];  } godot_pool_string_array;  #endif  /////// PoolVector2Array +#define GODOT_POOL_VECTOR2_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED -typedef struct godot_pool_vector2_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_VECTOR2_ARRAY_SIZE];  } godot_pool_vector2_array;  #endif  /////// PoolVector3Array +#define GODOT_POOL_VECTOR3_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED -typedef struct godot_pool_vector3_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_VECTOR3_ARRAY_SIZE];  } godot_pool_vector3_array;  #endif  /////// PoolColorArray +#define GODOT_POOL_COLOR_ARRAY_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED -typedef struct godot_pool_color_array { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_POOL_COLOR_ARRAY_SIZE];  } godot_pool_color_array;  #endif -#include "godot_array.h" -#include "godot_color.h" -#include "godot_vector2.h" -#include "godot_vector3.h" +#include "array.h" +#include "color.h" +#include "vector2.h" +#include "vector3.h" -#include "../godot.h" +#include "gdnative.h"  // byte diff --git a/modules/gdnative/godot/godot_quat.cpp b/modules/gdnative/godot/quat.cpp index 7235e4fcec..6800f7fc7e 100644 --- a/modules/gdnative/godot/godot_quat.cpp +++ b/modules/gdnative/godot/quat.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_quat.cpp                                                       */ +/*  quat.cpp                                                             */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_quat.h" +#include "quat.h"  #include "core/variant.h"  #include "core/math/quat.h" diff --git a/modules/gdnative/godot/godot_quat.h b/modules/gdnative/godot/quat.h index 2289b6cbab..b86cbacc62 100644 --- a/modules/gdnative/godot/godot_quat.h +++ b/modules/gdnative/godot/quat.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_quat.h                                                         */ +/*  quat.h                                                               */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,17 @@ extern "C" {  #include <stdint.h> +#define GODOT_QUAT_SIZE 16 +  #ifndef GODOT_CORE_API_GODOT_QUAT_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_QUAT_TYPE_DEFINED -typedef struct godot_quat { -	uint8_t _dont_touch_that[16]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_QUAT_SIZE];  } godot_quat;  #endif -#include "../godot.h" -#include "godot_vector3.h" +#include "gdnative.h" +#include "vector3.h"  void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w);  void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle); diff --git a/modules/gdnative/godot/godot_rect2.cpp b/modules/gdnative/godot/rect2.cpp index 0e456ea3ba..830d7bb496 100644 --- a/modules/gdnative/godot/godot_rect2.cpp +++ b/modules/gdnative/godot/rect2.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rect2.cpp                                                      */ +/*  rect2.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_rect2.h" +#include "rect2.h"  #include "core/variant.h"  #include "core/math/math_2d.h" diff --git a/modules/gdnative/godot/godot_rect2.h b/modules/gdnative/godot/rect2.h index 488a1204f7..7b6613d9dd 100644 --- a/modules/gdnative/godot/godot_rect2.h +++ b/modules/gdnative/godot/rect2.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rect2.h                                                        */ +/*  rect2.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -43,8 +43,8 @@ typedef struct godot_rect2 {  } godot_rect2;  #endif -#include "../godot.h" -#include "godot_vector2.h" +#include "gdnative.h" +#include "vector2.h"  void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size);  void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height); diff --git a/modules/gdnative/godot/godot_rect3.cpp b/modules/gdnative/godot/rect3.cpp index e524fa8463..0fabba5b7b 100644 --- a/modules/gdnative/godot/godot_rect3.cpp +++ b/modules/gdnative/godot/rect3.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rect3.cpp                                                      */ +/*  rect3.cpp                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_rect3.h" +#include "rect3.h"  #include "core/variant.h"  #include "core/math/rect3.h" diff --git a/modules/gdnative/godot/godot_rect3.h b/modules/gdnative/godot/rect3.h index 9e9a49ac27..638d89f76f 100644 --- a/modules/gdnative/godot/godot_rect3.h +++ b/modules/gdnative/godot/rect3.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rect3.h                                                        */ +/*  rect3.h                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,16 +36,18 @@ extern "C" {  #include <stdint.h> +#define GODOT_RECT3_SIZE 24 +  #ifndef GODOT_CORE_API_GODOT_RECT3_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_RECT3_TYPE_DEFINED -typedef struct godot_rect3 { -	uint8_t _dont_touch_that[24]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_RECT3_SIZE];  } godot_rect3;  #endif -#include "../godot.h" -#include "godot_plane.h" -#include "godot_vector3.h" +#include "gdnative.h" +#include "plane.h" +#include "vector3.h"  void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size); diff --git a/modules/gdnative/godot/godot_rid.cpp b/modules/gdnative/godot/rid.cpp index 343c004bff..2b724e554d 100644 --- a/modules/gdnative/godot/godot_rid.cpp +++ b/modules/gdnative/godot/rid.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rid.cpp                                                        */ +/*  rid.cpp                                                              */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_rid.h" +#include "rid.h"  #include "core/variant.h"  #include "core/resource.h" diff --git a/modules/gdnative/godot/godot_rid.h b/modules/gdnative/godot/rid.h index 25dc8d965e..92e101fd2e 100644 --- a/modules/gdnative/godot/godot_rid.h +++ b/modules/gdnative/godot/rid.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_rid.h                                                          */ +/*  rid.h                                                                */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,14 +36,16 @@ extern "C" {  #include <stdint.h> +#define GODOT_RID_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_RID_TYPE_DEFINED -typedef struct godot_rid { -	uint8_t _dont_touch_that[8]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_RID_SIZE];  } godot_rid;  #endif -#include "../godot.h" +#include "gdnative.h"  void GDAPI godot_rid_new(godot_rid *r_dest); diff --git a/modules/gdnative/godot/godot_string.cpp b/modules/gdnative/godot/string.cpp index 679011e715..e54ef3655f 100644 --- a/modules/gdnative/godot/godot_string.cpp +++ b/modules/gdnative/godot/string.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_string.cpp                                                     */ +/*  string.cpp                                                           */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_string.h" +#include "string.h"  #include "string_db.h"  #include "ustring.h" diff --git a/modules/gdnative/godot/godot_string.h b/modules/gdnative/godot/string.h index df848abb76..d4d6d6c1d0 100644 --- a/modules/gdnative/godot/godot_string.h +++ b/modules/gdnative/godot/string.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_string.h                                                       */ +/*  string.h                                                             */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -37,13 +37,16 @@ extern "C" {  #include <stdint.h>  #include <wchar.h> +#define GODOT_STRING_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED -typedef struct godot_string { -	uint8_t _dont_touch_that[8]; +#define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_STRING_SIZE];  } godot_string;  #endif -#include "../godot.h" +#include "gdnative.h"  void GDAPI godot_string_new(godot_string *r_dest);  void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src); diff --git a/modules/gdnative/godot/godot_transform.cpp b/modules/gdnative/godot/transform.cpp index eb9e1e207b..e566ed0b6e 100644 --- a/modules/gdnative/godot/godot_transform.cpp +++ b/modules/gdnative/godot/transform.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_transform.cpp                                                  */ +/*  transform.cpp                                                        */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_transform.h" +#include "transform.h"  #include "core/variant.h"  #include "core/math/transform.h" diff --git a/modules/gdnative/godot/godot_transform.h b/modules/gdnative/godot/transform.h index ee87e1d33f..d14190ec49 100644 --- a/modules/gdnative/godot/godot_transform.h +++ b/modules/gdnative/godot/transform.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_transform.h                                                    */ +/*  transform.h                                                          */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,17 +36,19 @@ extern "C" {  #include <stdint.h> +#define GODOT_TRANSFORM_SIZE 48 +  #ifndef GODOT_CORE_API_GODOT_TRANSFORM_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_TRANSFORM_TYPE_DEFINED -typedef struct godot_transform { -	uint8_t _dont_touch_that[48]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_TRANSFORM_SIZE];  } godot_transform;  #endif -#include "../godot.h" -#include "godot_basis.h" -#include "godot_variant.h" -#include "godot_vector3.h" +#include "basis.h" +#include "gdnative.h" +#include "variant.h" +#include "vector3.h"  void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin);  void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin); diff --git a/modules/gdnative/godot/godot_transform2d.cpp b/modules/gdnative/godot/transform2d.cpp index bdb5476f7d..01db3f7ae0 100644 --- a/modules/gdnative/godot/godot_transform2d.cpp +++ b/modules/gdnative/godot/transform2d.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_transform2d.cpp                                                */ +/*  transform2d.cpp                                                      */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_transform2d.h" +#include "transform2d.h"  #include "core/variant.h"  #include "core/math/math_2d.h" diff --git a/modules/gdnative/godot/godot_transform2d.h b/modules/gdnative/godot/transform2d.h index c375e90af7..7171e528f2 100644 --- a/modules/gdnative/godot/godot_transform2d.h +++ b/modules/gdnative/godot/transform2d.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_transform2d.h                                                  */ +/*  transform2d.h                                                        */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,16 +36,18 @@ extern "C" {  #include <stdint.h> +#define GODOT_TRANSFORM2D_SIZE 24 +  #ifndef GODOT_CORE_API_GODOT_TRANSFORM2D_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_TRANSFORM2D_TYPE_DEFINED -typedef struct godot_transform2d { -	uint8_t _dont_touch_that[24]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_TRANSFORM2D_SIZE];  } godot_transform2d;  #endif -#include "../godot.h" -#include "godot_variant.h" -#include "godot_vector2.h" +#include "gdnative.h" +#include "variant.h" +#include "vector2.h"  void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos);  void GDAPI godot_transform2d_new_axis_origin(godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin); diff --git a/modules/gdnative/godot/godot_variant.cpp b/modules/gdnative/godot/variant.cpp index c9607fb21a..3469058cfd 100644 --- a/modules/gdnative/godot/godot_variant.cpp +++ b/modules/gdnative/godot/variant.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_variant.cpp                                                    */ +/*  variant.cpp                                                          */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_variant.h" +#include "variant.h"  #include "core/variant.h"  #ifdef __cplusplus diff --git a/modules/gdnative/godot/godot_variant.h b/modules/gdnative/godot/variant.h index 9b6d287249..b56d5824fa 100644 --- a/modules/gdnative/godot/godot_variant.h +++ b/modules/gdnative/godot/variant.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_variant.h                                                      */ +/*  variant.h                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,9 +36,12 @@ extern "C" {  #include <stdint.h> +#define GODOT_VARIANT_SIZE 24 +  #ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED -typedef struct godot_variant { -	uint8_t _dont_touch_that[24]; +#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED +typedef struct { +	uint8_t _dont_touch_that[GODOT_VARIANT_SIZE];  } godot_variant;  #endif @@ -96,25 +99,25 @@ typedef struct godot_variant_call_error {  	godot_variant_type expected;  } godot_variant_call_error; -#include "godot_array.h" -#include "godot_basis.h" -#include "godot_color.h" -#include "godot_dictionary.h" -#include "godot_node_path.h" -#include "godot_plane.h" -#include "godot_pool_arrays.h" -#include "godot_quat.h" -#include "godot_rect2.h" -#include "godot_rect3.h" -#include "godot_rid.h" -#include "godot_string.h" -#include "godot_transform.h" -#include "godot_transform2d.h" -#include "godot_variant.h" -#include "godot_vector2.h" -#include "godot_vector3.h" - -#include "../godot.h" +#include "array.h" +#include "basis.h" +#include "color.h" +#include "dictionary.h" +#include "node_path.h" +#include "plane.h" +#include "pool_arrays.h" +#include "quat.h" +#include "rect2.h" +#include "rect3.h" +#include "rid.h" +#include "string.h" +#include "transform.h" +#include "transform2d.h" +#include "variant.h" +#include "vector2.h" +#include "vector3.h" + +#include "gdnative.h"  godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v); diff --git a/modules/gdnative/godot/godot_vector2.cpp b/modules/gdnative/godot/vector2.cpp index 0ced800872..6b40e31a89 100644 --- a/modules/gdnative/godot/godot_vector2.cpp +++ b/modules/gdnative/godot/vector2.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_vector2.cpp                                                    */ +/*  vector2.cpp                                                          */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_vector2.h" +#include "vector2.h"  #include "core/variant.h"  #include "core/math/math_2d.h" diff --git a/modules/gdnative/godot/godot_vector2.h b/modules/gdnative/godot/vector2.h index 9c7590fedf..9934ddadbb 100644 --- a/modules/gdnative/godot/godot_vector2.h +++ b/modules/gdnative/godot/vector2.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_vector2.h                                                      */ +/*  vector2.h                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,14 +36,16 @@ extern "C" {  #include <stdint.h> +#define GODOT_VECTOR2_SIZE 8 +  #ifndef GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED -typedef struct godot_vector2 { -	uint8_t _dont_touch_that[8]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_VECTOR2_SIZE];  } godot_vector2;  #endif -#include "../godot.h" +#include "gdnative.h"  void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y); diff --git a/modules/gdnative/godot/godot_vector3.cpp b/modules/gdnative/godot/vector3.cpp index adca0d1e2a..904cdad9d0 100644 --- a/modules/gdnative/godot/godot_vector3.cpp +++ b/modules/gdnative/godot/vector3.cpp @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_vector3.cpp                                                    */ +/*  vector3.cpp                                                          */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -27,7 +27,7 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#include "godot_vector3.h" +#include "vector3.h"  #include "core/variant.h"  #include "core/vector.h" diff --git a/modules/gdnative/godot/godot_vector3.h b/modules/gdnative/godot/vector3.h index 98d9ddf6ac..b5f8d0f49a 100644 --- a/modules/gdnative/godot/godot_vector3.h +++ b/modules/gdnative/godot/vector3.h @@ -1,5 +1,5 @@  /*************************************************************************/ -/*  godot_vector3.h                                                      */ +/*  vector3.h                                                            */  /*************************************************************************/  /*                       This file is part of:                           */  /*                           GODOT ENGINE                                */ @@ -36,15 +36,17 @@ extern "C" {  #include <stdint.h> +#define GODOT_VECTOR3_SIZE 12 +  #ifndef GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED  #define GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED -typedef struct godot_vector3 { -	uint8_t _dont_touch_that[12]; +typedef struct { +	uint8_t _dont_touch_that[GODOT_VECTOR3_SIZE];  } godot_vector3;  #endif -#include "../godot.h" -#include "godot_basis.h" +#include "basis.h" +#include "gdnative.h"  typedef enum {  	GODOT_VECTOR3_AXIS_X, diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 8789c9a267..20ac1ecc0c 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -33,34 +33,46 @@  #include "io/resource_loader.h"  #include "io/resource_saver.h" -GDNativeScriptLanguage *script_language_gdn = NULL; -ResourceFormatLoaderGDNativeScript *resource_loader_gdn = NULL; -ResourceFormatSaverGDNativeScript *resource_saver_gdn = NULL; -//ResourceFormatLoaderDLLibrary *resource_loader_dllib=NULL; +#include "core/os/os.h" -void register_gdnative_types() { +godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot_array *p_args) { +	if (handle == NULL) { +		ERR_PRINT("No valid library handle, can't call standard varcall procedure"); +		godot_variant ret; +		godot_variant_new_nil(&ret); +		return ret; +	} -	ClassDB::register_class<GDNativeLibrary>(); -	ClassDB::register_class<GDNativeScript>(); +	void *library_proc; +	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( +			handle, +			*(String *)p_procedure, +			library_proc); +	if (err != OK) { +		ERR_PRINT((String("GDNative procedure \"" + *(String *)p_procedure) + "\" does not exists and can't be called").utf8().get_data()); +		godot_variant ret; +		godot_variant_new_nil(&ret); +		return ret; +	} + +	godot_gdnative_procedure_fn proc; +	proc = (godot_gdnative_procedure_fn)library_proc; -	script_language_gdn = memnew(GDNativeScriptLanguage); -	ScriptServer::register_language(script_language_gdn); -	resource_loader_gdn = memnew(ResourceFormatLoaderGDNativeScript); -	ResourceLoader::add_resource_format_loader(resource_loader_gdn); -	resource_saver_gdn = memnew(ResourceFormatSaverGDNativeScript); -	ResourceSaver::add_resource_format_saver(resource_saver_gdn); +	return proc(NULL, p_args);  } -void unregister_gdnative_types() { +GDNativeCallRegistry *GDNativeCallRegistry::singleton; -	ScriptServer::unregister_language(script_language_gdn); +void register_gdnative_types() { -	if (script_language_gdn) -		memdelete(script_language_gdn); +	ClassDB::register_class<GDNativeLibrary>(); +	ClassDB::register_class<GDNative>(); + +	GDNativeCallRegistry::singleton = memnew(GDNativeCallRegistry); -	if (resource_loader_gdn) -		memdelete(resource_loader_gdn); +	GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall); +} -	if (resource_saver_gdn) -		memdelete(resource_saver_gdn); +void unregister_gdnative_types() { +	memdelete(GDNativeCallRegistry::singleton);  } diff --git a/modules/nativescript/SCsub b/modules/nativescript/SCsub new file mode 100644 index 0000000000..e980e40e8e --- /dev/null +++ b/modules/nativescript/SCsub @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +Import('env') + +mod_env = env.Clone() +mod_env.add_source_files(env.modules_sources, "*.cpp") +mod_env.Append(CPPPATH='#modules/gdnative') +mod_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN']) + +Export('mod_env') diff --git a/modules/gdnative/api_generator.cpp b/modules/nativescript/api_generator.cpp index 47162bfc49..47162bfc49 100644 --- a/modules/gdnative/api_generator.cpp +++ b/modules/nativescript/api_generator.cpp diff --git a/modules/gdnative/api_generator.h b/modules/nativescript/api_generator.h index a108d7a7b6..a108d7a7b6 100644 --- a/modules/gdnative/api_generator.h +++ b/modules/nativescript/api_generator.h diff --git a/modules/nativescript/config.py b/modules/nativescript/config.py new file mode 100644 index 0000000000..9f57b9bb74 --- /dev/null +++ b/modules/nativescript/config.py @@ -0,0 +1,8 @@ + + +def can_build(platform): +    return True + + +def configure(env): +    env.use_ptrcall = True diff --git a/modules/nativescript/godot_nativescript.cpp b/modules/nativescript/godot_nativescript.cpp new file mode 100644 index 0000000000..7da6d14d18 --- /dev/null +++ b/modules/nativescript/godot_nativescript.cpp @@ -0,0 +1,205 @@ +/*************************************************************************/ +/*  godot_nativescript.cpp                                               */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +#include "godot_nativescript.h" + +#include "nativescript.h" + +#include "class_db.h" +#include "error_macros.h" +#include "gdnative.h" +#include "global_constants.h" +#include "project_settings.h" +#include "variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern "C" void _native_script_hook() { +} + +#define NSL NativeScriptLanguage::get_singleton() + +// Script API + +void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { + +	String *s = (String *)p_gdnative_handle; + +	Map<StringName, NativeScriptDesc> *classes = &NSL->library_classes[*s]; + +	NativeScriptDesc desc; + +	desc.create_func = p_create_func; +	desc.destroy_func = p_destroy_func; +	desc.is_tool = false; + +	desc.base = p_base; + +	if (classes->has(p_base)) { +		desc.base_data = &(*classes)[p_base]; +		desc.base_native_type = desc.base_data->base_native_type; +	} else { +		desc.base_data = NULL; +		desc.base_native_type = p_base; +	} + +	classes->insert(p_name, desc); +} + +void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { + +	String *s = (String *)p_gdnative_handle; + +	Map<StringName, NativeScriptDesc> *classes = &NSL->library_classes[*s]; + +	NativeScriptDesc desc; + +	desc.create_func = p_create_func; +	desc.destroy_func = p_destroy_func; +	desc.is_tool = true; +	desc.base = p_base; + +	if (classes->has(p_base)) { +		desc.base_data = &(*classes)[p_base]; +		desc.base_native_type = desc.base_data->base_native_type; +	} else { +		desc.base_data = NULL; +		desc.base_native_type = p_base; +	} + +	classes->insert(p_name, desc); +} + +void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) { + +	String *s = (String *)p_gdnative_handle; + +	Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + +	if (!E) { +		ERR_EXPLAIN("Attempt to register method on non-existant class!"); +		ERR_FAIL(); +	} + +	NativeScriptDesc::Method method; +	method.method = p_method; +	method.rpc_mode = p_attr.rpc_type; +	method.info = MethodInfo(p_function_name); + +	E->get().methods.insert(p_function_name, method); +} + +void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) { + +	String *s = (String *)p_gdnative_handle; + +	Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + +	if (!E) { +		ERR_EXPLAIN("Attempt to register method on non-existant class!"); +		ERR_FAIL(); +	} + +	NativeScriptDesc::Property property; +	property.default_value = *(Variant *)&p_attr->default_value; +	property.getter = p_get_func; +	property.rset_mode = p_attr->rset_type; +	property.setter = p_set_func; +	property.info = PropertyInfo((Variant::Type)p_attr->type, +			p_path, +			(PropertyHint)p_attr->hint, +			*(String *)&p_attr->hint_string, +			(PropertyUsageFlags)p_attr->usage); + +	E->get().properties.insert(p_path, property); +} + +void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) { + +	String *s = (String *)p_gdnative_handle; + +	Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + +	if (!E) { +		ERR_EXPLAIN("Attempt to register method on non-existant class!"); +		ERR_FAIL(); +	} + +	List<PropertyInfo> args; +	Vector<Variant> default_args; + +	for (int i = 0; i < p_signal->num_args; i++) { +		PropertyInfo info; + +		godot_signal_argument arg = p_signal->args[i]; + +		info.hint = (PropertyHint)arg.hint; +		info.hint_string = *(String *)&arg.hint_string; +		info.name = *(String *)&arg.name; +		info.type = (Variant::Type)arg.type; +		info.usage = (PropertyUsageFlags)arg.usage; + +		args.push_back(info); +	} + +	for (int i = 0; i < p_signal->num_default_args; i++) { +		Variant *v; +		godot_signal_argument attrib = p_signal->args[i]; + +		v = (Variant *)&attrib.default_value; + +		default_args.push_back(*v); +	} + +	MethodInfo method_info; +	method_info.name = *(String *)&p_signal->name; +	method_info.arguments = args; +	method_info.default_arguments = default_args; + +	NativeScriptDesc::Signal signal; +	signal.signal = method_info; + +	E->get().signals_.insert(*(String *)&p_signal->name, signal); +} + +void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance) { +	Object *instance = (Object *)p_instance; +	if (!instance) +		return NULL; +	if (instance->get_script_instance() && instance->get_script_instance()->get_language() == NativeScriptLanguage::get_singleton()) { +		// return ((NativeScriptInstance *)instance->get_script_instance())->get_userdata(); +	} +	return NULL; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/gdnative/godot.h b/modules/nativescript/godot_nativescript.h index 1d86998291..cfd445086b 100644 --- a/modules/gdnative/godot.h +++ b/modules/nativescript/godot_nativescript.h @@ -27,8 +27,10 @@  /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */  /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */  /*************************************************************************/ -#ifndef GODOT_C_H -#define GODOT_C_H +#ifndef GODOT_NATIVESCRIPT_H +#define GODOT_NATIVESCRIPT_H + +#include <godot/gdnative.h>  #ifdef __cplusplus  extern "C" { @@ -70,203 +72,7 @@ extern "C" {  #include <stdbool.h>  #include <stdint.h> -#define GODOT_API_VERSION 1 - -////// Error - -typedef enum godot_error { -	GODOT_OK, -	GODOT_FAILED, ///< Generic fail error -	GODOT_ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable -	GODOT_ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet -	GODOT_ERR_UNAUTHORIZED, ///< Missing credentials for requested resource -	GODOT_ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5) -	GODOT_ERR_OUT_OF_MEMORY, ///< Out of memory -	GODOT_ERR_FILE_NOT_FOUND, -	GODOT_ERR_FILE_BAD_DRIVE, -	GODOT_ERR_FILE_BAD_PATH, -	GODOT_ERR_FILE_NO_PERMISSION, // (10) -	GODOT_ERR_FILE_ALREADY_IN_USE, -	GODOT_ERR_FILE_CANT_OPEN, -	GODOT_ERR_FILE_CANT_WRITE, -	GODOT_ERR_FILE_CANT_READ, -	GODOT_ERR_FILE_UNRECOGNIZED, // (15) -	GODOT_ERR_FILE_CORRUPT, -	GODOT_ERR_FILE_MISSING_DEPENDENCIES, -	GODOT_ERR_FILE_EOF, -	GODOT_ERR_CANT_OPEN, ///< Can't open a resource/socket/file -	GODOT_ERR_CANT_CREATE, // (20) -	GODOT_ERR_QUERY_FAILED, -	GODOT_ERR_ALREADY_IN_USE, -	GODOT_ERR_LOCKED, ///< resource is locked -	GODOT_ERR_TIMEOUT, -	GODOT_ERR_CANT_CONNECT, // (25) -	GODOT_ERR_CANT_RESOLVE, -	GODOT_ERR_CONNECTION_ERROR, -	GODOT_ERR_CANT_AQUIRE_RESOURCE, -	GODOT_ERR_CANT_FORK, -	GODOT_ERR_INVALID_DATA, ///< Data passed is invalid	(30) -	GODOT_ERR_INVALID_PARAMETER, ///< Parameter passed is invalid -	GODOT_ERR_ALREADY_EXISTS, ///< When adding, item already exists -	GODOT_ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist -	GODOT_ERR_DATABASE_CANT_READ, ///< database is full -	GODOT_ERR_DATABASE_CANT_WRITE, ///< database is full	(35) -	GODOT_ERR_COMPILATION_FAILED, -	GODOT_ERR_METHOD_NOT_FOUND, -	GODOT_ERR_LINK_FAILED, -	GODOT_ERR_SCRIPT_FAILED, -	GODOT_ERR_CYCLIC_LINK, // (40) -	GODOT_ERR_INVALID_DECLARATION, -	GODOT_ERR_DUPLICATE_SYMBOL, -	GODOT_ERR_PARSE_ERROR, -	GODOT_ERR_BUSY, -	GODOT_ERR_SKIP, // (45) -	GODOT_ERR_HELP, ///< user requested help!! -	GODOT_ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior. -	GODOT_ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames -	GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though -	GODOT_ERR_WTF = GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above -} godot_error; - -////// bool - -typedef bool godot_bool; - -#define GODOT_TRUE 1 -#define GODOT_FALSE 0 - -/////// int - -typedef int godot_int; - -/////// real - -typedef float godot_real; - -/////// Object (forward declared) -typedef void godot_object; - -/////// Brute force forward declarations for the rest -typedef struct godot_variant godot_variant; -typedef struct godot_string godot_string; -typedef struct godot_vector2 godot_vector2; -typedef struct godot_rect2 godot_rect2; -typedef struct godot_vector3 godot_vector3; -typedef struct godot_transform2d godot_transform2d; -typedef struct godot_plane godot_plane; -typedef struct godot_quat godot_quat; -typedef struct godot_rect3 godot_rect3; -typedef struct godot_basis godot_basis; -typedef struct godot_transform godot_transform; -typedef struct godot_color godot_color; -typedef struct godot_node_path godot_node_path; -typedef struct godot_rid godot_rid; -typedef struct godot_dictionary godot_dictionary; -typedef struct godot_array godot_array; -typedef struct godot_pool_byte_array godot_pool_byte_array; -typedef struct godot_pool_int_array godot_pool_int_array; -typedef struct godot_pool_real_array godot_pool_real_array; -typedef struct godot_pool_string_array godot_pool_string_array; -typedef struct godot_pool_vector2_array godot_pool_vector2_array; -typedef struct godot_pool_vector3_array godot_pool_vector3_array; -typedef struct godot_pool_color_array godot_pool_color_array; - -/////// String - -#include "godot/godot_string.h" - -////// Vector2 - -#include "godot/godot_vector2.h" - -////// Rect2 - -#include "godot/godot_rect2.h" - -////// Vector3 - -#include "godot/godot_vector3.h" - -////// Transform2D - -#include "godot/godot_transform2d.h" - -/////// Plane - -#include "godot/godot_plane.h" - -/////// Quat - -#include "godot/godot_quat.h" - -/////// Rect3 - -#include "godot/godot_rect3.h" - -/////// Basis - -#include "godot/godot_basis.h" - -/////// Transform - -#include "godot/godot_transform.h" - -/////// Color - -#include "godot/godot_color.h" - -/////// NodePath - -#include "godot/godot_node_path.h" - -/////// RID - -#include "godot/godot_rid.h" - -/////// Dictionary - -#include "godot/godot_dictionary.h" - -/////// Array - -#include "godot/godot_array.h" - -// single API file for Pool*Array -#include "godot/godot_pool_arrays.h" - -void GDAPI godot_object_destroy(godot_object *p_o); - -////// Variant - -#include "godot/godot_variant.h" - -////// Singleton API - -godot_object GDAPI *godot_global_get_singleton(char *p_name); // result shouldn't be freed - -////// MethodBind API - -typedef struct godot_method_bind { -	uint8_t _dont_touch_that[1]; // TODO -} godot_method_bind; - -godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname); -void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret); -godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error); -////// Script API - -typedef struct godot_native_init_options { -	godot_bool in_editor; -	uint64_t core_api_hash; -	uint64_t editor_api_hash; -	uint64_t no_api_hash; -} godot_native_init_options; - -typedef struct godot_native_terminate_options { -	godot_bool in_editor; -} godot_native_terminate_options; - -typedef enum godot_method_rpc_mode { +typedef enum {  	GODOT_METHOD_RPC_MODE_DISABLED,  	GODOT_METHOD_RPC_MODE_REMOTE,  	GODOT_METHOD_RPC_MODE_SYNC, @@ -274,11 +80,7 @@ typedef enum godot_method_rpc_mode {  	GODOT_METHOD_RPC_MODE_SLAVE,  } godot_method_rpc_mode; -typedef struct godot_method_attributes { -	godot_method_rpc_mode rpc_type; -} godot_method_attributes; - -typedef enum godot_property_hint { +typedef enum {  	GODOT_PROPERTY_HINT_NONE, ///< no hint provided.  	GODOT_PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step,slider; //slider is optional"  	GODOT_PROPERTY_HINT_EXP_RANGE, ///< hint_text = "min,max,step", exponential edit @@ -315,7 +117,7 @@ typedef enum godot_property_hint {  	GODOT_PROPERTY_HINT_MAX,  } godot_property_hint; -typedef enum godot_property_usage_flags { +typedef enum {  	GODOT_PROPERTY_USAGE_STORAGE = 1,  	GODOT_PROPERTY_USAGE_EDITOR = 2, @@ -340,7 +142,7 @@ typedef enum godot_property_usage_flags {  	GODOT_PROPERTY_USAGE_NOEDITOR = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_NETWORK,  } godot_property_usage_flags; -typedef struct godot_property_attributes { +typedef struct {  	godot_method_rpc_mode rset_type;  	godot_int type; @@ -350,50 +152,54 @@ typedef struct godot_property_attributes {  	godot_variant default_value;  } godot_property_attributes; -typedef struct godot_instance_create_func { +typedef struct {  	// instance pointer, method_data - return user data  	GDCALLINGCONV void *(*create_func)(godot_object *, void *);  	void *method_data;  	GDCALLINGCONV void (*free_func)(void *);  } godot_instance_create_func; -typedef struct godot_instance_destroy_func { +typedef struct {  	// instance pointer, method data, user data  	GDCALLINGCONV void (*destroy_func)(godot_object *, void *, void *);  	void *method_data;  	GDCALLINGCONV void (*free_func)(void *);  } godot_instance_destroy_func; -void GDAPI godot_script_register_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); +void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); -void GDAPI godot_script_register_tool_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); +void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); + +typedef struct { +	godot_method_rpc_mode rpc_type; +} godot_method_attributes; -typedef struct godot_instance_method { +typedef struct {  	// instance pointer, method data, user data, num args, args - return result as varaint  	GDCALLINGCONV godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **);  	void *method_data;  	GDCALLINGCONV void (*free_func)(void *);  } godot_instance_method; -void GDAPI godot_script_register_method(const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method); +void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method); -typedef struct godot_property_set_func { +typedef struct {  	// instance pointer, method data, user data, value -	GDCALLINGCONV void (*set_func)(godot_object *, void *, void *, godot_variant); +	GDCALLINGCONV void (*set_func)(godot_object *, void *, void *, godot_variant *);  	void *method_data;  	GDCALLINGCONV void (*free_func)(void *);  } godot_property_set_func; -typedef struct godot_property_get_func { +typedef struct {  	// instance pointer, method data, user data, value  	GDCALLINGCONV godot_variant (*get_func)(godot_object *, void *, void *);  	void *method_data;  	GDCALLINGCONV void (*free_func)(void *);  } godot_property_get_func; -void GDAPI godot_script_register_property(const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func); +void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func); -typedef struct godot_signal_argument { +typedef struct {  	godot_string name;  	godot_int type;  	godot_property_hint hint; @@ -402,7 +208,7 @@ typedef struct godot_signal_argument {  	godot_variant default_value;  } godot_signal_argument; -typedef struct godot_signal { +typedef struct {  	godot_string name;  	int num_args;  	godot_signal_argument *args; @@ -410,31 +216,12 @@ typedef struct godot_signal {  	godot_variant *default_args;  } godot_signal; -void GDAPI godot_script_register_signal(const char *p_name, const godot_signal *p_signal); - -void GDAPI *godot_native_get_userdata(godot_object *p_instance); - -// Calling convention? -typedef godot_object *(*godot_class_constructor)(); - -godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname); +void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal); -godot_dictionary GDAPI godot_get_global_constants(); - -////// System Functions - -//using these will help Godot track how much memory is in use in debug mode -void GDAPI *godot_alloc(int p_bytes); -void GDAPI *godot_realloc(void *p_ptr, int p_bytes); -void GDAPI godot_free(void *p_ptr); - -//print using Godot's error handler list -void GDAPI godot_print_error(const char *p_description, const char *p_function, const char *p_file, int p_line); -void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line); -void GDAPI godot_print(const godot_string *p_message); +void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance);  #ifdef __cplusplus  }  #endif -#endif // GODOT_C_H +#endif diff --git a/modules/nativescript/nativescript.cpp b/modules/nativescript/nativescript.cpp new file mode 100644 index 0000000000..661ae5371d --- /dev/null +++ b/modules/nativescript/nativescript.cpp @@ -0,0 +1,1088 @@ +/*************************************************************************/ +/*  nativescript.cpp                                                     */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +#include "nativescript.h" + +#include "modules/gdnative/godot/gdnative.h" + +#include "global_constants.h" +#include "io/file_access_encrypted.h" +#include "os/file_access.h" +#include "os/os.h" +#include "project_settings.h" + +#include "scene/main/scene_tree.h" +#include "scene/resources/scene_format_text.h" + +#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) +#include "api_generator.h" +#endif + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#endif + +////// Script stuff + +void NativeScript::_bind_methods() { +	ClassDB::bind_method(D_METHOD("set_class_name", "class_name:String"), &NativeScript::set_class_name); +	ClassDB::bind_method(D_METHOD("get_class_name:String"), &NativeScript::get_class_name); + +	ClassDB::bind_method(D_METHOD("set_library", "library:GDNativeLibrary"), &NativeScript::set_library); +	ClassDB::bind_method(D_METHOD("get_library:GDNativeLibrary"), &NativeScript::get_library); + +	ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "class_name"), "set_class_name", "get_class_name"); +	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library"); +} + +#define NSL NativeScriptLanguage::get_singleton() + +#ifdef TOOLS_ENABLED + +void NativeScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { +	NativeScriptDesc *script_data = get_script_desc(); + +	ERR_FAIL_COND(!script_data); + +	List<PropertyInfo> info; +	Map<StringName, Variant> values; + +	for (Map<StringName, NativeScriptDesc::Property>::Element *E = script_data->properties.front(); E; E = E->next()) { +		PropertyInfo p = E->get().info; +		p.name = String(E->key()); + +		info.push_back(p); +		values[p.name] = E->get().default_value; +	} + +	p_placeholder->update(info, values); +} + +void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { +	placeholders.erase(p_placeholder); +} + +#endif + +void NativeScript::set_class_name(String p_class_name) { +	class_name = p_class_name; +} + +String NativeScript::get_class_name() const { +	return class_name; +} + +void NativeScript::set_library(Ref<GDNativeLibrary> p_library) { +	if (!library.is_null()) { +		WARN_PRINT("library on NativeScript already set. Do nothing."); +		return; +	} +	library = p_library; + +	// See if this library was "registered" already. + +	lib_path = library->get_active_library_path(); +	Map<String, Ref<GDNative> >::Element *E = NSL->library_gdnatives.find(lib_path); + +	if (!E) { +		Ref<GDNative> gdn; +		gdn.instance(); +		gdn->set_library(library); + +		// TODO(karroffel): check the return value? +		gdn->initialize(); + +		NSL->library_gdnatives.insert(lib_path, gdn); + +		NSL->library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>()); + +		if (!NSL->library_script_users.has(lib_path)) +			NSL->library_script_users.insert(lib_path, Set<NativeScript *>()); + +		NSL->library_script_users[lib_path].insert(this); + +		void *args[1] = { +			(void *)&lib_path +		}; + +		// here the library registers all the classes and stuff. +		gdn->call_native_raw(NSL->_init_call_type, +				NSL->_init_call_name, +				NULL, +				1, +				args, +				NULL); +	} else { +		// already initialized. Nice. +	} +} + +Ref<GDNativeLibrary> NativeScript::get_library() const { +	return library; +} + +bool NativeScript::can_instance() const { + +	NativeScriptDesc *script_data = get_script_desc(); + +#ifdef TOOLS_ENABLED + +	return script_data || (!is_tool() && !ScriptServer::is_scripting_enabled()); +#else +	return script_data; +#endif +} + +// TODO(karroffel): implement this +Ref<Script> NativeScript::get_base_script() const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return Ref<Script>(); + +	Ref<NativeScript> ns = Ref<NativeScript>(NSL->create_script()); +	ns->set_class_name(script_data->base); +	ns->set_library(get_library()); +	return ns; +} + +StringName NativeScript::get_instance_base_type() const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return ""; + +	return script_data->base_native_type; +} + +ScriptInstance *NativeScript::instance_create(Object *p_this) { + +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) { +		return NULL; +	} + +#ifdef TOOLS_ENABLED +	if (!ScriptServer::is_scripting_enabled() && !is_tool()) { +		// placeholder for nodes. For tools we want the rool thing. + +		PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(NSL, Ref<Script>(this), p_this)); +		placeholders.insert(sins); + +		if (script_data->create_func.create_func) { +			script_data->create_func.create_func( +					(godot_object *)p_this, +					script_data->create_func.method_data); +		} + +		_update_placeholder(sins); + +		return sins; +	} +#endif + +	NativeScriptInstance *nsi = memnew(NativeScriptInstance); + +	nsi->owner = p_this; +	nsi->script = Ref<NativeScript>(this); + +#ifndef TOOLS_ENABLED +	if (!ScriptServer::is_scripting_enabled()) { +		nsi->userdata = NULL; +	} else { +		nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); +	} +#else +	nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); +#endif + +	instance_owners.insert(p_this); +	return nsi; +} + +bool NativeScript::instance_has(const Object *p_this) const { +	return instance_owners.has((Object *)p_this); +} + +bool NativeScript::has_source_code() const { +	return false; +} + +String NativeScript::get_source_code() const { +	return ""; +} + +void NativeScript::set_source_code(const String &p_code) { +} + +Error NativeScript::reload(bool p_keep_state) { +	return FAILED; +} + +bool NativeScript::has_method(const StringName &p_method) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	while (script_data) { +		if (script_data->methods.has(p_method)) +			return true; + +		script_data = script_data->base_data; +	} +	return false; +} + +MethodInfo NativeScript::get_method_info(const StringName &p_method) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return MethodInfo(); + +	while (script_data) { +		Map<StringName, NativeScriptDesc::Method>::Element *M = script_data->methods.find(p_method); + +		if (M) +			return M->get().info; + +		script_data = script_data->base_data; +	} +	return MethodInfo(); +} + +bool NativeScript::is_tool() const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (script_data) +		return script_data->is_tool; + +	return false; +} + +String NativeScript::get_node_type() const { +	return ""; // NOTE(karroffel): uhm? +} + +ScriptLanguage *NativeScript::get_language() const { +	return NativeScriptLanguage::get_singleton(); +} + +bool NativeScript::has_script_signal(const StringName &p_signal) const { +	NativeScriptDesc *script_data = get_script_desc(); +	if (!script_data) +		return false; +	return script_data->signals_.has(p_signal); +} + +void NativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return; + +	Set<MethodInfo> signals_; + +	while (script_data) { + +		for (Map<StringName, NativeScriptDesc::Signal>::Element *S = script_data->signals_.front(); S; S = S->next()) { +			signals_.insert(S->get().signal); +		} + +		script_data = script_data->base_data; +	} + +	for (Set<MethodInfo>::Element *E = signals_.front(); E; E = E->next()) { +		r_signals->push_back(E->get()); +	} +} + +bool NativeScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return false; + +	Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_property); + +	if (!P) +		return false; + +	r_value = P->get().default_value; +	return true; +} + +void NativeScript::update_exports() { +} + +void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return; + +	Set<MethodInfo> methods; + +	while (script_data) { + +		for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { +			methods.insert(E->get().info); +		} + +		script_data = script_data->base_data; +	} + +	for (Set<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { +		p_list->push_back(E->get()); +	} +} + +void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const { +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) +		return; + +	Set<PropertyInfo> properties; + +	while (script_data) { + +		for (Map<StringName, NativeScriptDesc::Property>::Element *E = script_data->properties.front(); E; E = E->next()) { +			properties.insert(E->get().info); +		} + +		script_data = script_data->base_data; +	} + +	for (Set<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { +		p_list->push_back(E->get()); +	} +} + +Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + +	if (lib_path.empty() || class_name.empty() || library.is_null()) { +		r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; +		return Variant(); +	} + +	NativeScriptDesc *script_data = get_script_desc(); + +	if (!script_data) { +		r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; +		return Variant(); +	} + +	r_error.error = Variant::CallError::CALL_OK; + +	REF ref; +	Object *owner = NULL; + +	if (!(script_data->base_native_type == "")) { +		owner = ClassDB::instance(script_data->base_native_type); +	} else { +		owner = memnew(Reference); +	} + +	Reference *r = owner->cast_to<Reference>(); +	if (r) { +		ref = REF(r); +	} + +	// GDScript does it like this: _create_instance(p_args, p_argcount, owner, r != NULL, r_error); +	// TODO(karroffel): support varargs for constructors. + +	NativeScriptInstance *instance = (NativeScriptInstance *)instance_create(owner); + +	owner->set_script_instance(instance); + +	if (!instance) { +		if (ref.is_null()) { +			memdelete(owner); //no owner, sorry +		} +		return Variant(); +	} + +	if (ref.is_valid()) { +		return ref; +	} else { +		return owner; +	} +} + +// TODO(karroffel): implement this +NativeScript::NativeScript() { +	library = Ref<GDNative>(); +	lib_path = ""; +	class_name = ""; +} + +// TODO(karroffel): implement this +NativeScript::~NativeScript() { +	NSL->library_script_users[lib_path].erase(this); +} + +////// ScriptInstance stuff + +#define GET_SCRIPT_DESC() script->get_script_desc() + +void NativeScriptInstance::_ml_call_reversed(NativeScriptDesc *script_data, const StringName &p_method, const Variant **p_args, int p_argcount) { +	if (script_data->base_data) { +		_ml_call_reversed(script_data->base_data, p_method, p_args, p_argcount); +	} + +	Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); +	if (E) { +		godot_variant res = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); +		godot_variant_destroy(&res); +	} +} + +bool NativeScriptInstance::set(const StringName &p_name, const Variant &p_value) { +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { +		Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name); +		if (P) { +			P->get().setter.set_func((godot_object *)owner, +					P->get().setter.method_data, +					userdata, +					(godot_variant *)&p_value); +			return true; +		} + +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_set"); +		if (E) { +			Variant name = p_name; +			const Variant *args[2] = { &name, &p_value }; + +			E->get().method.method((godot_object *)owner, +					E->get().method.method_data, +					userdata, +					2, +					(godot_variant **)args); +			return true; +		} + +		script_data = script_data->base_data; +	} +	return false; +} +bool NativeScriptInstance::get(const StringName &p_name, Variant &r_ret) const { +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { +		Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name); +		if (P) { +			godot_variant value; +			value = P->get().getter.get_func((godot_object *)owner, +					P->get().setter.method_data, +					userdata); +			r_ret = *(Variant *)&value; +			godot_variant_destroy(&value); +			return true; +		} + +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_get"); +		if (E) { +			Variant name = p_name; +			const Variant *args[1] = { &name }; + +			godot_variant result; +			result = E->get().method.method((godot_object *)owner, +					E->get().method.method_data, +					userdata, +					1, +					(godot_variant **)args); +			r_ret = *(Variant *)&result; +			godot_variant_destroy(&result); +			if (r_ret.get_type() == Variant::NIL) { +				return false; +			} +			return true; +		} + +		script_data = script_data->base_data; +	} +	return false; +} + +void NativeScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { + +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_get_property_list"); +		if (E) { + +			godot_variant result; +			result = E->get().method.method((godot_object *)owner, +					E->get().method.method_data, +					userdata, +					0, +					NULL); +			Variant res = *(Variant *)&result; +			godot_variant_destroy(&result); + +			if (res.get_type() != Variant::ARRAY) { +				ERR_EXPLAIN("_get_property_list must return an array of dictionaries"); +				ERR_FAIL(); +			} + +			Array arr = res; +			for (int i = 0; i < arr.size(); i++) { +				Dictionary d = arr[i]; + +				ERR_CONTINUE(!d.has("name")); +				ERR_CONTINUE(!d.has("type")); + +				PropertyInfo info; + +				info.type = Variant::Type(d["type"].operator int64_t()); +				ERR_CONTINUE(info.type < 0 || info.type >= Variant::VARIANT_MAX); + +				info.name = d["name"]; +				ERR_CONTINUE(info.name == ""); + +				if (d.has("hint")) { +					info.hint = PropertyHint(d["hint"].operator int64_t()); +				} + +				if (d.has("hint_string")) { +					info.hint_string = d["hint_string"]; +				} + +				if (d.has("usage")) { +					info.usage = d["usage"]; +				} + +				p_properties->push_back(info); +			} +		} + +		script_data = script_data->base_data; +	} +	return; +} + +Variant::Type NativeScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { + +		Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name); +		if (P) { +			*r_is_valid = true; +			return P->get().info.type; +		} + +		script_data = script_data->base_data; +	} +	return Variant::NIL; +} + +void NativeScriptInstance::get_method_list(List<MethodInfo> *p_list) const { +	script->get_method_list(p_list); +} + +bool NativeScriptInstance::has_method(const StringName &p_method) const { +	return script->has_method(p_method); +} + +Variant NativeScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); +		if (E) { +			godot_variant result; +			result = E->get().method.method((godot_object *)owner, +					E->get().method.method_data, +					userdata, +					p_argcount, +					(godot_variant **)p_args); +			Variant res = *(Variant *)&result; +			godot_variant_destroy(&result); +			r_error.error = Variant::CallError::CALL_OK; +			return res; +		} + +		script_data = script_data->base_data; +	} + +	r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; +	return Variant(); +} + +void NativeScriptInstance::notification(int p_notification) { +	Variant value = p_notification; +	const Variant *args[1] = { &value }; +	call_multilevel("_notification", args, 1); +} + +Ref<Script> NativeScriptInstance::get_script() const { +	return script; +} + +NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { + +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); +		if (E) { +			switch (E->get().rpc_mode) { +				case GODOT_METHOD_RPC_MODE_DISABLED: +					return RPC_MODE_DISABLED; +				case GODOT_METHOD_RPC_MODE_REMOTE: +					return RPC_MODE_REMOTE; +				case GODOT_METHOD_RPC_MODE_SYNC: +					return RPC_MODE_SYNC; +				case GODOT_METHOD_RPC_MODE_MASTER: +					return RPC_MODE_MASTER; +				case GODOT_METHOD_RPC_MODE_SLAVE: +					return RPC_MODE_SLAVE; +				default: +					return RPC_MODE_DISABLED; +			} +		} + +		script_data = script_data->base_data; +	} + +	return RPC_MODE_DISABLED; +} + +// TODO(karroffel): implement this +NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { + +		Map<StringName, NativeScriptDesc::Property>::Element *E = script_data->properties.find(p_variable); +		if (E) { +			switch (E->get().rset_mode) { +				case GODOT_METHOD_RPC_MODE_DISABLED: +					return RPC_MODE_DISABLED; +				case GODOT_METHOD_RPC_MODE_REMOTE: +					return RPC_MODE_REMOTE; +				case GODOT_METHOD_RPC_MODE_SYNC: +					return RPC_MODE_SYNC; +				case GODOT_METHOD_RPC_MODE_MASTER: +					return RPC_MODE_MASTER; +				case GODOT_METHOD_RPC_MODE_SLAVE: +					return RPC_MODE_SLAVE; +				default: +					return RPC_MODE_DISABLED; +			} +		} + +		script_data = script_data->base_data; +	} + +	return RPC_MODE_DISABLED; +} + +ScriptLanguage *NativeScriptInstance::get_language() { +	return NativeScriptLanguage::get_singleton(); +} + +void NativeScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	while (script_data) { +		Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); +		if (E) { +			godot_variant res = E->get().method.method((godot_object *)owner, +					E->get().method.method_data, +					userdata, +					p_argcount, +					(godot_variant **)p_args); +			godot_variant_destroy(&res); +		} +		script_data = script_data->base_data; +	} +} + +void NativeScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	if (script_data) { +		_ml_call_reversed(script_data, p_method, p_args, p_argcount); +	} +} + +NativeScriptInstance::~NativeScriptInstance() { + +	NativeScriptDesc *script_data = GET_SCRIPT_DESC(); + +	if (!script_data) +		return; + +	script_data->destroy_func.destroy_func((godot_object *)owner, script_data->destroy_func.method_data, userdata); + +	if (owner) { +		script->instance_owners.erase(owner); +	} +} + +////// ScriptingLanguage stuff + +NativeScriptLanguage *NativeScriptLanguage::singleton; + +extern "C" void _native_script_hook(); +void NativeScriptLanguage::_hacky_api_anchor() { +	_native_script_hook(); +} + +void NativeScriptLanguage::_unload_stuff() { +	for (Map<String, Map<StringName, NativeScriptDesc> >::Element *L = library_classes.front(); L; L = L->next()) { +		for (Map<StringName, NativeScriptDesc>::Element *C = L->get().front(); C; C = C->next()) { + +			// free property stuff first +			for (Map<StringName, NativeScriptDesc::Property>::Element *P = C->get().properties.front(); P; P = P->next()) { +				if (P->get().getter.free_func) +					P->get().getter.free_func(P->get().getter.method_data); + +				if (P->get().setter.free_func) +					P->get().setter.free_func(P->get().setter.method_data); +			} + +			// free method stuff +			for (Map<StringName, NativeScriptDesc::Method>::Element *M = C->get().methods.front(); M; M = M->next()) { +				if (M->get().method.free_func) +					M->get().method.free_func(M->get().method.method_data); +			} + +			// free constructor/destructor +			if (C->get().create_func.free_func) +				C->get().create_func.free_func(C->get().create_func.method_data); + +			if (C->get().destroy_func.free_func) +				C->get().destroy_func.free_func(C->get().destroy_func.method_data); +		} +	} +} + +NativeScriptLanguage::NativeScriptLanguage() { +	NativeScriptLanguage::singleton = this; +} + +// TODO(karroffel): implement this +NativeScriptLanguage::~NativeScriptLanguage() { +	_unload_stuff(); + +	for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { + +		L->get()->terminate(); +		NSL->library_classes.clear(); +		NSL->library_gdnatives.clear(); +		NSL->library_script_users.clear(); +	} +} + +String NativeScriptLanguage::get_name() const { +	return "NativeScript"; +} + +void _add_reload_node() { +#ifdef TOOLS_ENABLED +	NativeReloadNode *rn = memnew(NativeReloadNode); +	EditorNode::get_singleton()->add_child(rn); +#endif +} + +// TODO(karroffel): implement this +void NativeScriptLanguage::init() { + +#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) + +	List<String> args = OS::get_singleton()->get_cmdline_args(); + +	List<String>::Element *E = args.find("--gdnative-generate-json-api"); + +	if (E && E->next()) { +		if (generate_c_api(E->next()->get()) != OK) { +			ERR_PRINT("Failed to generate C API\n"); +		} +	} +#endif + +#ifdef TOOLS_ENABLED +	EditorNode::add_init_callback(&_add_reload_node); +#endif +} +String NativeScriptLanguage::get_type() const { +	return "NativeScript"; +} +String NativeScriptLanguage::get_extension() const { +	return "gdns"; +} +Error NativeScriptLanguage::execute_file(const String &p_path) { +	return OK; // Qué? +} +void NativeScriptLanguage::finish() { +	_unload_stuff(); +} +void NativeScriptLanguage::get_reserved_words(List<String> *p_words) const { +} +void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { +} +void NativeScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { +} + +// TODO(karroffel): implement this +Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { +	NativeScript *s = memnew(NativeScript); +	s->set_class_name(p_class_name); +	// TODO(karroffel): use p_base_class_name +	return Ref<NativeScript>(s); +} +bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { +	return false; +} + +Script *NativeScriptLanguage::create_script() const { +	NativeScript *script = memnew(NativeScript); +	return script; +} +bool NativeScriptLanguage::has_named_classes() const { +	return true; +} +int NativeScriptLanguage::find_function(const String &p_function, const String &p_code) const { +	return -1; +} +String NativeScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { +	return ""; +} +void NativeScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const { +} +void NativeScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { +} + +// Debugging stuff here. Not used for now. +String NativeScriptLanguage::debug_get_error() const { +	return ""; +} +int NativeScriptLanguage::debug_get_stack_level_count() const { +	return -1; +} +int NativeScriptLanguage::debug_get_stack_level_line(int p_level) const { +	return -1; +} +String NativeScriptLanguage::debug_get_stack_level_function(int p_level) const { +	return ""; +} +String NativeScriptLanguage::debug_get_stack_level_source(int p_level) const { +	return ""; +} +void NativeScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { +} +void NativeScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { +} +void NativeScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { +} +String NativeScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { +	return ""; +} +// Debugging stuff end. + +void NativeScriptLanguage::reload_all_scripts() { +} + +void NativeScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { +} +void NativeScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { +	p_extensions->push_back("gdns"); +} + +void NativeScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { +} + +void NativeScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const { +} + +void NativeScriptLanguage::profiling_start() { +} + +void NativeScriptLanguage::profiling_stop() { +} + +int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { +	return -1; +} + +int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { +	return -1; +} + +void NativeReloadNode::_bind_methods() { +	ClassDB::bind_method(D_METHOD("_notification"), &NativeReloadNode::_notification); +} + +void NativeReloadNode::_notification(int p_what) { +#ifdef TOOLS_ENABLED + +	switch (p_what) { +		case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + +			print_line("unload"); + +			NSL->_unload_stuff(); +			for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { + +				L->get()->terminate(); +				NSL->library_classes.erase(L->key()); +			} + +		} break; + +		case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + +			print_line("load"); + +			Set<StringName> libs_to_remove; + +			for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { + +				if (!L->get()->initialize()) { +					libs_to_remove.insert(L->key()); +					continue; +				} + +				NSL->library_classes.insert(L->key(), Map<StringName, NativeScriptDesc>()); + +				void *args[1] = { +					(void *)&L->key() +				}; + +				// here the library registers all the classes and stuff. +				L->get()->call_native_raw(NSL->_init_call_type, +						NSL->_init_call_name, +						NULL, +						1, +						args, +						NULL); + +				for (Map<String, Set<NativeScript *> >::Element *U = NSL->library_script_users.front(); U; U = U->next()) { +					for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) { +						NativeScript *script = S->get(); + +						if (script->placeholders.size() == 0) +							continue; + +						for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) { +							script->_update_placeholder(P->get()); +						} +					} +				} +			} + +			for (Set<StringName>::Element *R = libs_to_remove.front(); R; R = R->next()) { +				NSL->library_gdnatives.erase(R->get()); +			} + +			/* +			for (Set<NativeLibrary *>::Element *L = libs_to_reload.front(); L; L = L->next()) { + +				GDNativeLibrary *lib = L->get()->dllib; + +				lib->_terminate(); +				lib->_initialize(); + +				// update placeholders (if any) + +				Set<GDNativeScript *> scripts; + +				for (Set<GDNativeScript *>::Element *S = GDNativeScriptLanguage::get_singleton()->script_list.front(); S; S = S->next()) { + +					if (lib->native_library->scripts.has(S->get()->get_script_name())) { +						GDNativeScript *script = S->get(); +						script->script_data = lib->get_script_data(script->get_script_name()); +						scripts.insert(script); +					} +				} + +				for (Set<GDNativeScript *>::Element *S = scripts.front(); S; S = S->next()) { +					GDNativeScript *script = S->get(); +					if (script->placeholders.size() == 0) +						continue; + +					for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) { +						PlaceHolderScriptInstance *p = P->get(); +						script->_update_placeholder(p); +					} +				} +			} +			*/ + +		} break; +		default: { +		}; +	} +#endif +} + +RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error) { +	ResourceFormatLoaderText rsflt; +	return rsflt.load(p_path, p_original_path, r_error); +} + +void ResourceFormatLoaderNativeScript::get_recognized_extensions(List<String> *p_extensions) const { +	p_extensions->push_back("gdns"); +} + +bool ResourceFormatLoaderNativeScript::handles_type(const String &p_type) const { +	return (p_type == "Script" || p_type == "NativeScript"); +} + +String ResourceFormatLoaderNativeScript::get_resource_type(const String &p_path) const { +	String el = p_path.get_extension().to_lower(); +	if (el == "gdns") +		return "NativeScript"; +	return ""; +} + +Error ResourceFormatSaverNativeScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { +	ResourceFormatSaverText rfst; +	return rfst.save(p_path, p_resource, p_flags); +} + +bool ResourceFormatSaverNativeScript::recognize(const RES &p_resource) const { +	return p_resource->cast_to<NativeScript>() != NULL; +} + +void ResourceFormatSaverNativeScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { +	if (p_resource->cast_to<NativeScript>()) { +		p_extensions->push_back("gdns"); +	} +} diff --git a/modules/nativescript/nativescript.h b/modules/nativescript/nativescript.h new file mode 100644 index 0000000000..0578ffb680 --- /dev/null +++ b/modules/nativescript/nativescript.h @@ -0,0 +1,281 @@ +/*************************************************************************/ +/*  nativescript.h                                                       */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +#ifndef NATIVE_SCRIPT_H +#define NATIVE_SCRIPT_H + +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "os/thread_safe.h" +#include "resource.h" +#include "scene/main/node.h" +#include "script_language.h" +#include "self_list.h" + +#include "godot_nativescript.h" +#include "modules/gdnative/gdnative.h" + +struct NativeScriptDesc { + +	struct Method { +		godot_instance_method method; +		MethodInfo info; +		int rpc_mode; +	}; +	struct Property { +		godot_property_set_func setter; +		godot_property_get_func getter; +		PropertyInfo info; +		Variant default_value; +		int rset_mode; +	}; + +	struct Signal { +		MethodInfo signal; +	}; + +	Map<StringName, Method> methods; +	Map<StringName, Property> properties; +	Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals +	StringName base; +	StringName base_native_type; +	NativeScriptDesc *base_data; +	godot_instance_create_func create_func; +	godot_instance_destroy_func destroy_func; + +	bool is_tool; + +	inline NativeScriptDesc() +		: methods(), +		  properties(), +		  signals_(), +		  base(), +		  base_native_type() { +		zeromem(&create_func, sizeof(godot_instance_create_func)); +		zeromem(&destroy_func, sizeof(godot_instance_destroy_func)); +	} +}; + +class NativeScript : public Script { +	GDCLASS(NativeScript, Script) + +#ifdef TOOLS_ENABLED +	Set<PlaceHolderScriptInstance *> placeholders; +	void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); +	virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); +#endif + +	friend class NativeScriptInstance; +	friend class NativeScriptLanguage; +	friend class NativeReloadNode; +	friend class GDNativeLibrary; + +	Ref<GDNativeLibrary> library; + +	String lib_path; + +	String class_name; + +	Set<Object *> instance_owners; + +protected: +	static void _bind_methods(); + +public: +	inline NativeScriptDesc *get_script_desc() const; + +	void set_class_name(String p_class_name); +	String get_class_name() const; + +	void set_library(Ref<GDNativeLibrary> library); +	Ref<GDNativeLibrary> get_library() const; + +	virtual bool can_instance() const; + +	virtual Ref<Script> get_base_script() const; //for script inheritance + +	virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so +	virtual ScriptInstance *instance_create(Object *p_this); +	virtual bool instance_has(const Object *p_this) const; + +	virtual bool has_source_code() const; +	virtual String get_source_code() const; +	virtual void set_source_code(const String &p_code); +	virtual Error reload(bool p_keep_state = false); + +	virtual bool has_method(const StringName &p_method) const; +	virtual MethodInfo get_method_info(const StringName &p_method) const; + +	virtual bool is_tool() const; + +	virtual String get_node_type() const; + +	virtual ScriptLanguage *get_language() const; + +	virtual bool has_script_signal(const StringName &p_signal) const; +	virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; + +	virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const; + +	virtual void update_exports(); //editor tool +	virtual void get_script_method_list(List<MethodInfo> *p_list) const; +	virtual void get_script_property_list(List<PropertyInfo> *p_list) const; + +	Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error); + +	NativeScript(); +	~NativeScript(); +}; + +class NativeScriptInstance : public ScriptInstance { + +	friend class NativeScript; + +	Object *owner; +	Ref<NativeScript> script; + +	void *userdata; + +	void _ml_call_reversed(NativeScriptDesc *script_data, const StringName &p_method, const Variant **p_args, int p_argcount); + +public: +	virtual bool set(const StringName &p_name, const Variant &p_value); +	virtual bool get(const StringName &p_name, Variant &r_ret) const; +	virtual void get_property_list(List<PropertyInfo> *p_properties) const; +	virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const; +	virtual void get_method_list(List<MethodInfo> *p_list) const; +	virtual bool has_method(const StringName &p_method) const; +	virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); +	virtual void notification(int p_notification); +	virtual Ref<Script> get_script() const; +	virtual RPCMode get_rpc_mode(const StringName &p_method) const; +	virtual RPCMode get_rset_mode(const StringName &p_variable) const; +	virtual ScriptLanguage *get_language(); + +	virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); +	virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); + +	~NativeScriptInstance(); +}; + +class NativeReloadNode; + +class NativeScriptLanguage : public ScriptLanguage { + +	friend class NativeScript; +	friend class NativeScriptInstance; +	friend class NativeReloadNode; + +private: +	static NativeScriptLanguage *singleton; + +	void _unload_stuff(); + +public: +	Map<String, Map<StringName, NativeScriptDesc> > library_classes; +	Map<String, Ref<GDNative> > library_gdnatives; + +	Map<String, Set<NativeScript *> > library_script_users; + +	const StringName _init_call_type = "nativescript_init"; +	const StringName _init_call_name = "godot_nativescript_init"; + +	NativeScriptLanguage(); +	~NativeScriptLanguage(); + +	inline static NativeScriptLanguage *get_singleton() { +		return singleton; +	} + +	void _hacky_api_anchor(); + +	virtual String get_name() const; +	virtual void init(); +	virtual String get_type() const; +	virtual String get_extension() const; +	virtual Error execute_file(const String &p_path); +	virtual void finish(); +	virtual void get_reserved_words(List<String> *p_words) const; +	virtual void get_comment_delimiters(List<String> *p_delimiters) const; +	virtual void get_string_delimiters(List<String> *p_delimiters) const; +	virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; +	virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const; +	virtual Script *create_script() const; +	virtual bool has_named_classes() const; +	virtual int find_function(const String &p_function, const String &p_code) const; +	virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; +	virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; +	virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); +	virtual String debug_get_error() const; +	virtual int debug_get_stack_level_count() const; +	virtual int debug_get_stack_level_line(int p_level) const; +	virtual String debug_get_stack_level_function(int p_level) const; +	virtual String debug_get_stack_level_source(int p_level) const; +	virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth); +	virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth); +	virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth); +	virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth); +	virtual void reload_all_scripts(); +	virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload); +	virtual void get_recognized_extensions(List<String> *p_extensions) const; +	virtual void get_public_functions(List<MethodInfo> *p_functions) const; +	virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const; +	virtual void profiling_start(); +	virtual void profiling_stop(); +	virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); +	virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); +}; + +inline NativeScriptDesc *NativeScript::get_script_desc() const { +	Map<StringName, NativeScriptDesc>::Element *E = NativeScriptLanguage::singleton->library_classes[lib_path].find(class_name); +	return E ? &E->get() : NULL; +} + +class NativeReloadNode : public Node { +	GDCLASS(NativeReloadNode, Node) +public: +	static void _bind_methods(); +	void _notification(int p_what); +}; + +class ResourceFormatLoaderNativeScript : public ResourceFormatLoader { +public: +	virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); +	virtual void get_recognized_extensions(List<String> *p_extensions) const; +	virtual bool handles_type(const String &p_type) const; +	virtual String get_resource_type(const String &p_path) const; +}; + +class ResourceFormatSaverNativeScript : public ResourceFormatSaver { +	virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); +	virtual bool recognize(const RES &p_resource) const; +	virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; +}; + +#endif // GDNATIVE_H diff --git a/modules/nativescript/register_types.cpp b/modules/nativescript/register_types.cpp new file mode 100644 index 0000000000..6c88b04a56 --- /dev/null +++ b/modules/nativescript/register_types.cpp @@ -0,0 +1,93 @@ +/*************************************************************************/ +/*  register_types.cpp                                                   */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +#include "register_types.h" + +#include "io/resource_loader.h" +#include "io/resource_saver.h" + +#include "nativescript.h" + +#include "core/os/os.h" + +NativeScriptLanguage *native_script_language; + +typedef void (*native_script_init_fn)(void *); + +void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p_num_args, void **args, void *r_ret) { +	if (p_handle == NULL) { +		ERR_PRINT("No valid library handle, can't call nativescript init procedure"); +		return; +	} + +	void *library_proc; +	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( +			p_handle, +			*(String *)p_proc_name, +			library_proc); +	if (err != OK) { +		ERR_PRINT((String("GDNative procedure \"" + *(String *)p_proc_name) + "\" does not exists and can't be called").utf8().get_data()); +		return; +	} + +	native_script_init_fn fn = (native_script_init_fn)library_proc; + +	fn(args[0]); +} + +ResourceFormatLoaderNativeScript *resource_loader_gdns = NULL; +ResourceFormatSaverNativeScript *resource_saver_gdns = NULL; + +void register_nativescript_types() { +	native_script_language = memnew(NativeScriptLanguage); + +	ClassDB::register_class<NativeScript>(); + +	ScriptServer::register_language(native_script_language); + +	GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_init_call_type, init_call_cb); + +	resource_saver_gdns = memnew(ResourceFormatSaverNativeScript); +	ResourceSaver::add_resource_format_saver(resource_saver_gdns); + +	resource_loader_gdns = memnew(ResourceFormatLoaderNativeScript); +	ResourceLoader::add_resource_format_loader(resource_loader_gdns); +} + +void unregister_nativescript_types() { + +	memdelete(resource_loader_gdns); + +	memdelete(resource_saver_gdns); + +	if (native_script_language) { +		ScriptServer::unregister_language(native_script_language); +		memdelete(native_script_language); +	} +} diff --git a/modules/nativescript/register_types.h b/modules/nativescript/register_types.h new file mode 100644 index 0000000000..319da9c42f --- /dev/null +++ b/modules/nativescript/register_types.h @@ -0,0 +1,31 @@ +/*************************************************************************/ +/*  register_types.h                                                     */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ +/*                                                                       */ +/* 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.                */ +/*************************************************************************/ +void register_nativescript_types(); +void unregister_nativescript_types();  |