summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/extension/gdextension_interface.cpp37
-rw-r--r--core/extension/gdextension_interface.h31
-rw-r--r--core/object/class_db.h3
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/object.h3
-rw-r--r--core/object/script_language.h3
-rw-r--r--core/object/script_language_extension.cpp1
-rw-r--r--core/object/script_language_extension.h10
8 files changed, 94 insertions, 0 deletions
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index b4541de8fe..a70ad5262f 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -1048,6 +1048,41 @@ static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDE
return reinterpret_cast<GDExtensionScriptInstancePtr>(script_instance_extension);
}
+static GDExtensionScriptInstancePtr gdextension_placeholder_script_instance_create(GDExtensionObjectPtr p_language, GDExtensionObjectPtr p_script, GDExtensionObjectPtr p_owner) {
+ ScriptLanguage *language = (ScriptLanguage *)p_language;
+ Ref<Script> script;
+ script.reference_ptr((Script *)p_script);
+ Object *owner = (Object *)p_owner;
+
+ PlaceHolderScriptInstance *placeholder = memnew(PlaceHolderScriptInstance(language, script, owner));
+ return reinterpret_cast<GDExtensionScriptInstancePtr>(placeholder);
+}
+
+static void gdextension_placeholder_script_instance_update(GDExtensionScriptInstancePtr p_placeholder, GDExtensionConstTypePtr p_properties, GDExtensionConstTypePtr p_values) {
+ PlaceHolderScriptInstance *placeholder = dynamic_cast<PlaceHolderScriptInstance *>(reinterpret_cast<ScriptInstance *>(p_placeholder));
+ ERR_FAIL_COND_MSG(!placeholder, "Unable to update placeholder, expected a PlaceHolderScriptInstance but received an invalid type.");
+
+ const Array &properties = *reinterpret_cast<const Array *>(p_properties);
+ const Dictionary &values = *reinterpret_cast<const Dictionary *>(p_values);
+
+ List<PropertyInfo> properties_list;
+ HashMap<StringName, Variant> values_map;
+
+ for (int i = 0; i < properties.size(); i++) {
+ Dictionary d = properties[i];
+ properties_list.push_back(PropertyInfo::from_dict(d));
+ }
+
+ List<Variant> keys;
+ values.get_key_list(&keys);
+
+ for (const Variant &E : keys) {
+ values_map.insert(E, values[E]);
+ }
+
+ placeholder->update(properties_list, values_map);
+}
+
static GDExtensionScriptInstancePtr gdextension_object_get_script_instance(GDExtensionConstObjectPtr p_object, GDExtensionConstObjectPtr p_language) {
if (!p_object || !p_language) {
return nullptr;
@@ -1235,6 +1270,8 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(ref_get_object);
REGISTER_INTERFACE_FUNC(ref_set_object);
REGISTER_INTERFACE_FUNC(script_instance_create);
+ REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
+ REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
REGISTER_INTERFACE_FUNC(object_get_script_instance);
REGISTER_INTERFACE_FUNC(classdb_construct_object);
REGISTER_INTERFACE_FUNC(classdb_get_method_bind);
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index cfc21473d6..a86abf2a7e 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -2127,6 +2127,37 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
/**
+ * @name placeholder_script_instance_create
+ * @since 4.2
+ *
+ * Creates a placeholder script instance for a given script and instance.
+ *
+ * This interface is optional as a custom placeholder could also be created with script_instance_create().
+ *
+ * @param p_language A pointer to a ScriptLanguage.
+ * @param p_script A pointer to a Script.
+ * @param p_owner A pointer to an Object.
+ *
+ * @return A pointer to a PlaceHolderScriptInstance object.
+ */
+typedef GDExtensionScriptInstancePtr (*GDExtensionInterfacePlaceHolderScriptInstanceCreate)(GDExtensionObjectPtr p_language, GDExtensionObjectPtr p_script, GDExtensionObjectPtr p_owner);
+
+/**
+ * @name placeholder_script_instance_update
+ * @since 4.2
+ *
+ * Updates a placeholder script instance with the given properties and values.
+ *
+ * The passed in placeholder must be an instance of PlaceHolderScriptInstance
+ * such as the one returned by placeholder_script_instance_create().
+ *
+ * @param p_placeholder A pointer to a PlaceHolderScriptInstance.
+ * @param p_properties A pointer to an Array of Dictionary representing PropertyInfo.
+ * @param p_values A pointer to a Dictionary mapping StringName to Variant values.
+ */
+typedef void (*GDExtensionInterfacePlaceHolderScriptInstanceUpdate)(GDExtensionScriptInstancePtr p_placeholder, GDExtensionConstTypePtr p_properties, GDExtensionConstTypePtr p_values);
+
+/**
* @name object_get_script_instance
* @since 4.2
*
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 3aae3b452e..57469f03d2 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -187,6 +187,7 @@ public:
template <class T>
static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
+ static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
@@ -201,6 +202,7 @@ public:
template <class T>
static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
+ static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
@@ -221,6 +223,7 @@ public:
template <class T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
+ static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 4ae0ecdefd..b803d57cd9 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -526,6 +526,10 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
void Object::validate_property(PropertyInfo &p_property) const {
_validate_propertyv(p_property);
+
+ if (script_instance) { // Call it last to allow user altering already validated properties.
+ script_instance->validate_property(p_property);
+ }
}
bool Object::property_can_revert(const StringName &p_name) const {
@@ -1604,6 +1608,8 @@ void Object::_bind_methods() {
plget.return_val.hint_string = "Dictionary";
BIND_OBJ_CORE_METHOD(plget);
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::NIL, "_validate_property", PropertyInfo(Variant::DICTIONARY, "property")));
+
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_property_can_revert", PropertyInfo(Variant::STRING_NAME, "property")));
MethodInfo mipgr("_property_get_revert", PropertyInfo(Variant::STRING_NAME, "property"));
mipgr.return_val.name = "Variant";
diff --git a/core/object/object.h b/core/object/object.h
index 318dbf98de..561e5b8fe3 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -382,6 +382,7 @@ private:
friend class ::ClassDB; \
\
public: \
+ typedef m_class self_type; \
static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \
virtual String get_class() const override { \
if (_get_extension()) { \
@@ -557,6 +558,8 @@ class ScriptInstance;
class Object {
public:
+ typedef Object self_type;
+
enum ConnectFlags {
CONNECT_DEFERRED = 1,
CONNECT_PERSIST = 2, // hint for scene to save this connection
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 3ea6a6e4c3..9d83a12bbd 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -141,6 +141,7 @@ public:
#ifdef TOOLS_ENABLED
virtual Vector<DocData::ClassDoc> get_documentation() const = 0;
+ virtual String get_class_icon_path() const = 0;
virtual PropertyInfo get_class_category() const;
#endif // TOOLS_ENABLED
@@ -179,6 +180,7 @@ public:
virtual bool get(const StringName &p_name, Variant &r_ret) const = 0;
virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const = 0;
+ virtual void validate_property(PropertyInfo &p_property) const = 0;
virtual bool property_can_revert(const StringName &p_name) const = 0;
virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const = 0;
@@ -462,6 +464,7 @@ public:
virtual bool get(const StringName &p_name, Variant &r_ret) const override;
virtual void get_property_list(List<PropertyInfo> *p_properties) const override;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override;
+ virtual void validate_property(PropertyInfo &p_property) const override {}
virtual bool property_can_revert(const StringName &p_name) const override { return false; };
virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { return false; };
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 0df9d58334..bf8bac476a 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -52,6 +52,7 @@ void ScriptExtension::_bind_methods() {
GDVIRTUAL_BIND(_reload, "keep_state");
GDVIRTUAL_BIND(_get_documentation);
+ GDVIRTUAL_BIND(_get_class_icon_path);
GDVIRTUAL_BIND(_has_method, "method");
GDVIRTUAL_BIND(_get_method_info, "method");
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 1a0ec29479..6edbcdaeee 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -77,6 +77,7 @@ public:
EXBIND1R(Error, reload, bool)
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_documentation)
+ GDVIRTUAL0RC(String, _get_class_icon_path)
#ifdef TOOLS_ENABLED
virtual Vector<DocData::ClassDoc> get_documentation() const override {
TypedArray<Dictionary> doc;
@@ -89,6 +90,12 @@ public:
return class_doc;
}
+
+ virtual String get_class_icon_path() const override {
+ String ret;
+ GDVIRTUAL_CALL(_get_class_icon_path, ret);
+ return ret;
+ }
#endif // TOOLS_ENABLED
EXBIND1RC(bool, has_method, const StringName &)
@@ -675,6 +682,9 @@ public:
}
return Variant::NIL;
}
+ virtual void validate_property(PropertyInfo &p_property) const override {
+ // TODO
+ }
virtual bool property_can_revert(const StringName &p_name) const override {
if (native_info->property_can_revert_func) {