summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/extension/gdnative_interface.cpp2
-rw-r--r--core/extension/gdnative_interface.h2
-rw-r--r--core/extension/native_extension.cpp21
-rw-r--r--core/extension/native_extension.h2
-rw-r--r--doc/classes/Resource.xml3
-rw-r--r--doc/classes/Tween.xml18
-rw-r--r--editor/code_editor.cpp6
-rw-r--r--editor/inspector_dock.cpp128
-rw-r--r--editor/inspector_dock.h8
-rw-r--r--editor/plugins/material_editor_plugin.cpp12
-rw-r--r--platform/javascript/display_server_javascript.cpp11
-rw-r--r--platform/linuxbsd/display_server_x11.cpp3
-rw-r--r--scene/animation/tween.cpp11
-rw-r--r--scene/animation/tween.h4
14 files changed, 178 insertions, 53 deletions
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index a65bdd16dc..77229a784d 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -1005,6 +1005,8 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.classdb_register_extension_class_method = nullptr;
gdni.classdb_register_extension_class_integer_constant = nullptr;
gdni.classdb_register_extension_class_property = nullptr;
+ gdni.classdb_register_extension_class_property_group = nullptr;
+ gdni.classdb_register_extension_class_property_subgroup = nullptr;
gdni.classdb_register_extension_class_signal = nullptr;
gdni.classdb_unregister_extension_class = nullptr;
}
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 30346f233f..13aa273bc5 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -438,6 +438,8 @@ typedef struct {
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
+ void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
} GDNativeInterface;
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index a3cd7ca14c..635e53fa9c 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -184,6 +184,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value);
}
+
void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
NativeExtension *self = (NativeExtension *)p_library;
@@ -202,6 +203,24 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
}
+void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'.");
+
+ ClassDB::add_property_group(class_name, p_group_name, p_prefix);
+}
+
+void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'.");
+
+ ClassDB::add_property_subgroup(class_name, p_subgroup_name, p_prefix);
+}
+
void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
NativeExtension *self = (NativeExtension *)p_library;
@@ -325,6 +344,8 @@ void NativeExtension::initialize_native_extensions() {
gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method;
gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property;
+ gdnative_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group;
+ gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
}
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 9b1ebe0ed7..52e869ad4d 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -50,6 +50,8 @@ class NativeExtension : public Resource {
static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
+ static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 65dedf5280..efb0339aa7 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -16,7 +16,8 @@
<return type="Resource" />
<argument index="0" name="subresources" type="bool" default="false" />
<description>
- Duplicates the resource, returning a new resource. By default, sub-resources are shared between resource copies for efficiency. This can be changed by passing [code]true[/code] to the [code]subresources[/code] argument which will copy the subresources.
+ Duplicates the resource, returning a new resource with the exported members copied. [b]Note:[/b] To duplicate the resource the constructor is called without arguments. This method will error when the constructor doesn't have default values.
+ By default, sub-resources are shared between resource copies for efficiency. This can be changed by passing [code]true[/code] to the [code]subresources[/code] argument which will copy the subresources.
[b]Note:[/b] If [code]subresources[/code] is [code]true[/code], this method will only perform a shallow copy. Nested resources within subresources will not be duplicated and will still be shared.
[b]Note:[/b] When duplicating a resource, only [code]export[/code]ed properties are copied. Other properties will be set to their default value in the new resource.
</description>
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 372a6e7ebf..ede6e2fdd5 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -58,8 +58,8 @@
[codeblock]
var tween = create_tween().set_parallel(true)
tween.tween_property(...)
- tween.tween_property(...) #will run parallelly with above
- tween.chain().tween_property(...) #will run after two above are finished
+ tween.tween_property(...) # Will run parallelly with above.
+ tween.chain().tween_property(...) # Will run after two above are finished.
[/codeblock]
</description>
</method>
@@ -215,11 +215,9 @@
Creates and appends an [IntervalTweener]. This method can be used to create delays in the tween animation, as an alternative for using the delay in other [Tweener]s or when there's no animation (in which case the [Tween] acts as a timer). [code]time[/code] is the length of the interval, in seconds.
Example: creating an interval in code execution.
[codeblock]
- #... some code
- var tween = create_tween()
- tween.tween_interval(2)
- await tween.finished
- #... more code
+ # ... some code
+ await create_tween().tween_interval(2).finished
+ # ... more code
[/codeblock]
Example: creating an object that moves back and forth and jumps every few seconds.
[codeblock]
@@ -236,15 +234,15 @@
<method name="tween_method">
<return type="MethodTweener" />
<argument index="0" name="method" type="Callable" />
- <argument index="1" name="from" type="float" />
- <argument index="2" name="to" type="float" />
+ <argument index="1" name="from" type="Variant" />
+ <argument index="2" name="to" type="Variant" />
<argument index="3" name="duration" type="float" />
<description>
Creates and appends a [MethodTweener]. This method is similar to a combination of [method tween_callback] and [method tween_property]. It calls a method over time with a tweened value provided as an argument. The value is tweened between [code]from[/code] and [code]to[/code] over the time specified by [code]duration[/code], in seconds. Use [method Callable.bind] to bind additional arguments for the call. You can use [method MethodTweener.set_ease] and [method MethodTweener.set_trans] to tweak the easing and transition of the value or [method MethodTweener.set_delay] to delay the tweening.
Example: making a 3D object look from one point to another point.
[codeblock]
var tween = create_tween()
- tween.tween_method(look_at.bind(Vector3.UP), Vector3(-1, 0, -1), Vector3(1, 0, -1), 1) #the look_at() method takes up vector as second argument
+ tween.tween_method(look_at.bind(Vector3.UP), Vector3(-1, 0, -1), Vector3(1, 0, -1), 1) # The look_at() method takes up vector as second argument.
[/codeblock]
Example: setting a text of a [Label], using an intermediate method and after a delay.
[codeblock]
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 5599076c40..0c49a7169d 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -834,11 +834,9 @@ void CodeTextEditor::_line_col_changed() {
}
StringBuilder sb;
- sb.append("(");
- sb.append(itos(text_editor->get_caret_line() + 1).lpad(3));
- sb.append(",");
+ sb.append(itos(text_editor->get_caret_line() + 1).lpad(4));
+ sb.append(" : ");
sb.append(itos(positional_column + 1).lpad(3));
- sb.append(")");
line_and_col_txt->set_text(sb.as_string());
}
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 778046f45c..04ddf3552b 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -30,11 +30,22 @@
#include "inspector_dock.h"
-#include "editor/editor_node.h"
-#include "editor/editor_settings.h"
+#include "editor/editor_scale.h"
#include "editor/plugins/animation_player_editor_plugin.h"
void InspectorDock::_menu_option(int p_option) {
+ _menu_option_confirm(p_option, false);
+}
+
+void InspectorDock::_menu_confirm_current() {
+ _menu_option_confirm(current_option, true);
+}
+
+void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) {
+ if (!p_confirmed) {
+ current_option = p_option;
+ }
+
switch (p_option) {
case EXPAND_ALL: {
_menu_expandall();
@@ -82,39 +93,81 @@ void InspectorDock::_menu_option(int p_option) {
} break;
case OBJECT_UNIQUE_RESOURCES: {
- editor_data->apply_changes_in_editors();
- if (current) {
- List<PropertyInfo> props;
- current->get_property_list(&props);
- Map<RES, RES> duplicates;
- for (const PropertyInfo &E : props) {
- if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
- continue;
- }
+ if (!p_confirmed) {
+ Vector<String> resource_propnames;
- Variant v = current->get(E.name);
- if (v.is_ref()) {
+ if (current) {
+ List<PropertyInfo> props;
+ current->get_property_list(&props);
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
+
+ Variant v = current->get(E->get().name);
REF ref = v;
- if (ref.is_valid()) {
- RES res = ref;
- if (res.is_valid()) {
- if (!duplicates.has(res)) {
- duplicates[res] = res->duplicate();
- }
- res = duplicates[res];
+ RES res = ref;
+ if (v.is_ref() && ref.is_valid() && res.is_valid()) {
+ // Valid resource which would be duplicated if action is confirmed.
+ resource_propnames.append(E->get().name);
+ }
+ }
+ }
+
+ if (resource_propnames.size()) {
+ unique_resources_list_tree->clear();
+ TreeItem *root = unique_resources_list_tree->create_item();
- current->set(E.name, res);
- editor->get_inspector()->update_property(E.name);
+ for (int i = 0; i < resource_propnames.size(); i++) {
+ String propname = resource_propnames[i].replace("/", " / ");
+
+ TreeItem *ti = unique_resources_list_tree->create_item(root);
+ ti->set_text(0, bool(EDITOR_GET("interface/inspector/capitalize_properties")) ? propname.capitalize() : propname);
+ }
+
+ unique_resources_confirmation->popup_centered();
+ } else {
+ unique_resources_confirmation->set_text(TTR("This object has no resources."));
+ current_option = -1;
+ unique_resources_confirmation->popup_centered();
+ }
+ } else {
+ editor_data->apply_changes_in_editors();
+
+ if (current) {
+ List<PropertyInfo> props;
+ current->get_property_list(&props);
+ Map<RES, RES> duplicates;
+ for (const PropertyInfo &prop_info : props) {
+ if (!(prop_info.usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
+
+ Variant v = current->get(prop_info.name);
+ if (v.is_ref()) {
+ REF ref = v;
+ if (ref.is_valid()) {
+ RES res = ref;
+ if (res.is_valid()) {
+ if (!duplicates.has(res)) {
+ duplicates[res] = res->duplicate();
+ }
+ res = duplicates[res];
+
+ current->set(prop_info.name, res);
+ editor->get_inspector()->update_property(prop_info.name);
+ }
}
}
}
}
- }
- editor_data->get_undo_redo().clear_history();
+ editor_data->get_undo_redo().clear_history();
- editor->get_editor_plugins_over()->edit(nullptr);
- editor->get_editor_plugins_over()->edit(current);
+ editor->get_editor_plugins_over()->edit(nullptr);
+ editor->get_editor_plugins_over()->edit(current);
+ }
} break;
@@ -619,6 +672,29 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
warning->hide();
warning->connect("pressed", callable_mp(this, &InspectorDock::_warning_pressed));
+ unique_resources_confirmation = memnew(ConfirmationDialog);
+ add_child(unique_resources_confirmation);
+
+ VBoxContainer *container = memnew(VBoxContainer);
+ unique_resources_confirmation->add_child(container);
+
+ Label *top_label = memnew(Label);
+ top_label->set_text(TTR("The following resources will be duplicated and embedded within this resource/object."));
+ container->add_child(top_label);
+
+ unique_resources_list_tree = memnew(Tree);
+ unique_resources_list_tree->set_hide_root(true);
+ unique_resources_list_tree->set_columns(1);
+ unique_resources_list_tree->set_column_title(0, TTR("Property"));
+ unique_resources_list_tree->set_custom_minimum_size(Size2(0, 200 * EDSCALE));
+ container->add_child(unique_resources_list_tree);
+
+ Label *bottom_label = memnew(Label);
+ bottom_label->set_text(TTR("This cannot be undone. Are you sure?"));
+ container->add_child(bottom_label);
+
+ unique_resources_confirmation->connect("confirmed", callable_mp(this, &InspectorDock::_menu_confirm_current));
+
warning_dialog = memnew(AcceptDialog);
editor->get_gui_base()->add_child(warning_dialog);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index 6615845b66..5bf6a34617 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -40,8 +40,6 @@
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/control.h"
-#include "scene/gui/label.h"
-#include "scene/gui/popup_menu.h"
class EditorNode;
@@ -92,7 +90,13 @@ class InspectorDock : public VBoxContainer {
Button *warning;
AcceptDialog *warning_dialog;
+ int current_option = -1;
+ ConfirmationDialog *unique_resources_confirmation;
+ Tree *unique_resources_list_tree;
+
void _menu_option(int p_option);
+ void _menu_confirm_current();
+ void _menu_option_confirm(int p_option, bool p_confirmed);
void _new_resource();
void _load_resource(const String &p_type = "");
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 94966d4fe6..30945826bb 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -278,6 +278,8 @@ Ref<Resource> StandardMaterial3DConversionPlugin::convert(const Ref<Resource> &p
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
@@ -315,6 +317,8 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
@@ -352,6 +356,8 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
@@ -389,6 +395,8 @@ Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource>
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
@@ -426,6 +434,8 @@ Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> &
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
@@ -463,5 +473,7 @@ Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> &
}
smat->set_render_priority(mat->get_render_priority());
+ smat->set_local_to_scene(mat->is_local_to_scene());
+ smat->set_name(mat->get_name());
return smat;
}
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index b43614eb99..be4d2cba20 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -497,9 +497,10 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript
ev->set_button_mask(MouseButton(input->get_mouse_button_mask() | button_flag));
input->parse_input_event(ev);
- ev->set_pressed(false);
- ev->set_button_mask(MouseButton(input->get_mouse_button_mask() & ~button_flag));
- input->parse_input_event(ev);
+ Ref<InputEventMouseButton> release = ev->duplicate();
+ release->set_pressed(false);
+ release->set_button_mask(MouseButton(input->get_mouse_button_mask() & ~button_flag));
+ input->parse_input_event(release);
return true;
}
@@ -508,7 +509,6 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript
EM_BOOL DisplayServerJavaScript::touch_press_callback(int p_event_type, const EmscriptenTouchEvent *p_event, void *p_user_data) {
DisplayServerJavaScript *display = get_singleton();
Ref<InputEventScreenTouch> ev;
- ev.instantiate();
int lowest_id_index = -1;
for (int i = 0; i < p_event->numTouches; ++i) {
const EmscriptenTouchPoint &touch = p_event->touches[i];
@@ -516,6 +516,7 @@ EM_BOOL DisplayServerJavaScript::touch_press_callback(int p_event_type, const Em
lowest_id_index = i;
if (!touch.isChanged)
continue;
+ ev.instantiate();
ev->set_index(touch.identifier);
ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY));
display->touches[i] = ev->get_position();
@@ -534,7 +535,6 @@ EM_BOOL DisplayServerJavaScript::touch_press_callback(int p_event_type, const Em
EM_BOOL DisplayServerJavaScript::touchmove_callback(int p_event_type, const EmscriptenTouchEvent *p_event, void *p_user_data) {
DisplayServerJavaScript *display = get_singleton();
Ref<InputEventScreenDrag> ev;
- ev.instantiate();
int lowest_id_index = -1;
for (int i = 0; i < p_event->numTouches; ++i) {
const EmscriptenTouchPoint &touch = p_event->touches[i];
@@ -542,6 +542,7 @@ EM_BOOL DisplayServerJavaScript::touchmove_callback(int p_event_type, const Emsc
lowest_id_index = i;
if (!touch.isChanged)
continue;
+ ev.instantiate();
ev->set_index(touch.identifier);
ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY));
Point2 &prev = display->touches[i];
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index a39941339a..5c6824cf44 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -3614,7 +3614,8 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
+ "Please update your drivers or if you have a very old or integrated GPU, upgrade it.\n"
+ "If you have updated your graphics drivers recently, try rebooting.",
"Unable to initialize Video driver");
}
return ds;
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 3018fd3ae6..2847031375 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -60,6 +60,11 @@ Ref<PropertyTweener> Tween::tween_property(Object *p_target, NodePath p_property
ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
+#ifdef DEBUG_ENABLED
+ Variant::Type property_type = p_target->get_indexed(p_property.get_as_property_path().get_subnames()).get_type();
+ ERR_FAIL_COND_V_MSG(property_type != p_to.get_type(), Ref<PropertyTweener>(), "Type mismatch between property and final value: " + Variant::get_type_name(property_type) + " and " + Variant::get_type_name(p_to.get_type()));
+#endif
+
Ref<PropertyTweener> tweener = memnew(PropertyTweener(p_target, p_property, p_to, p_duration));
append(tweener);
return tweener;
@@ -83,7 +88,7 @@ Ref<CallbackTweener> Tween::tween_callback(Callable p_callback) {
return tweener;
}
-Ref<MethodTweener> Tween::tween_method(Callable p_callback, float p_from, float p_to, float p_duration) {
+Ref<MethodTweener> Tween::tween_method(Callable p_callback, Variant p_from, Variant p_to, float p_duration) {
ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
@@ -496,6 +501,8 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f
}
Variant Tween::calculate_delta_value(Variant p_intial_val, Variant p_final_val) {
+ ERR_FAIL_COND_V_MSG(p_intial_val.get_type() != p_final_val.get_type(), p_intial_val, "Type mismatch between initial and final value: " + Variant::get_type_name(p_intial_val.get_type()) + " and " + Variant::get_type_name(p_final_val.get_type()));
+
switch (p_intial_val.get_type()) {
case Variant::BOOL: {
return (int)p_final_val - (int)p_intial_val;
@@ -888,7 +895,7 @@ void MethodTweener::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ease", "ease"), &MethodTweener::set_ease);
}
-MethodTweener::MethodTweener(Callable p_callback, float p_from, float p_to, float p_duration) {
+MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration) {
callback = p_callback;
initial_val = p_from;
delta_val = tween->calculate_delta_value(p_from, p_to);
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 953d573539..6a48d332b8 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -128,7 +128,7 @@ public:
Ref<PropertyTweener> tween_property(Object *p_target, NodePath p_property, Variant p_to, float p_duration);
Ref<IntervalTweener> tween_interval(float p_time);
Ref<CallbackTweener> tween_callback(Callable p_callback);
- Ref<MethodTweener> tween_method(Callable p_callback, float p_from, float p_to, float p_duration);
+ Ref<MethodTweener> tween_method(Callable p_callback, Variant p_from, Variant p_to, float p_duration);
void append(Ref<Tweener> p_tweener);
bool custom_step(float p_delta);
@@ -258,7 +258,7 @@ public:
void start() override;
bool step(float &r_delta) override;
- MethodTweener(Callable p_callback, float p_from, float p_to, float p_duration);
+ MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration);
MethodTweener();
protected: