summaryrefslogtreecommitdiff
path: root/modules/gdnative/gdnative.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdnative/gdnative.cpp')
-rw-r--r--modules/gdnative/gdnative.cpp76
1 files changed, 61 insertions, 15 deletions
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 43b309ae36..09859d95bd 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -77,11 +77,9 @@ Error NativeLibrary::initialize(NativeLibrary *&p_native_lib, const StringName p
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?
@@ -393,6 +391,54 @@ void GDNativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
}
}
+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;
}
@@ -440,6 +486,8 @@ void GDNativeScript::_bind_methods() {
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");
}
@@ -1167,27 +1215,25 @@ void GDNativeReloadNode::_notification(int p_what) {
// update placeholders (if any)
- GDNativeScript *script = NULL;
+ 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())) {
- script = S->get();
+ GDNativeScript *script = S->get();
script->script_data = lib->get_script_data(script->get_script_name());
- break;
+ scripts.insert(script);
}
}
- if (script == NULL) {
- // new class, cool. Nothing to do here
- continue;
- }
-
- if (script->placeholders.size() == 0)
- continue;
+ 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);
+ for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) {
+ PlaceHolderScriptInstance *p = P->get();
+ script->_update_placeholder(p);
+ }
}
}