diff options
-rw-r--r-- | doc/classes/SceneTree.xml | 7 | ||||
-rw-r--r-- | doc/classes/Vector4.xml | 2 | ||||
-rw-r--r-- | doc/classes/Vector4i.xml | 61 | ||||
-rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 15 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 80 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 7 | ||||
-rw-r--r-- | scene/main/window.cpp | 4 |
8 files changed, 136 insertions, 45 deletions
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 417703ff01..221e627e35 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -58,8 +58,13 @@ <return type="SceneTreeTimer" /> <param index="0" name="time_sec" type="float" /> <param index="1" name="process_always" type="bool" default="true" /> + <param index="2" name="process_in_physics" type="bool" default="false" /> + <param index="3" name="ignore_time_scale" type="bool" default="false" /> <description> - Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this [SceneTree]. If [param process_always] is set to [code]false[/code], pausing the [SceneTree] will also pause the timer. + Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this [SceneTree]. + If [code]process_always[/code] is set to [code]false[/code], pausing the [SceneTree] will also pause the timer. + If [code]process_in_physics[/code] is set to [code]true[/code], will update the [SceneTreeTimer] during the physics frame instead of the process frame (fixed framerate processing). + If [code]ignore_time_scale[/code] is set to [code]true[/code], will ignore [member Engine.time_scale] and update the [SceneTreeTimer] with the actual frame delta. Commonly used to create a one-shot delay timer as in the following example: [codeblocks] [gdscript] diff --git a/doc/classes/Vector4.xml b/doc/classes/Vector4.xml index 743e2c2fcc..fdc93f82ec 100644 --- a/doc/classes/Vector4.xml +++ b/doc/classes/Vector4.xml @@ -28,7 +28,7 @@ <return type="Vector4" /> <param index="0" name="from" type="Vector4i" /> <description> - Constructs a new [Vector4] from [Vector4i]. + Constructs a new [Vector4] from the given [Vector4i]. </description> </constructor> <constructor name="Vector4"> diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml index 9a36c3c4fa..3eea93ce1f 100644 --- a/doc/classes/Vector4i.xml +++ b/doc/classes/Vector4i.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Vector4i" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Vector used for 4D math using integer coordinates. </brief_description> <description> + 4-element structure that can be used to represent 4D grid coordinates or sets of integers. + It uses integer coordinates. See [Vector4] for its floating-point counterpart. </description> <tutorials> </tutorials> @@ -10,18 +13,21 @@ <constructor name="Vector4i"> <return type="Vector4i" /> <description> + Constructs a default-initialized [Vector4i] with all components set to [code]0[/code]. </description> </constructor> <constructor name="Vector4i"> <return type="Vector4i" /> <param index="0" name="from" type="Vector4i" /> <description> + Constructs a [Vector4i] as a copy of the given [Vector4i]. </description> </constructor> <constructor name="Vector4i"> <return type="Vector4i" /> <param index="0" name="from" type="Vector4" /> <description> + Constructs a new [Vector4i] from the given [Vector4]. </description> </constructor> <constructor name="Vector4i"> @@ -31,6 +37,7 @@ <param index="2" name="z" type="int" /> <param index="3" name="w" type="int" /> <description> + Returns a [Vector4i] with the given components. </description> </constructor> </constructors> @@ -38,6 +45,7 @@ <method name="abs" qualifiers="const"> <return type="Vector4i" /> <description> + Returns a new vector with all components in absolute values (i.e. positive). </description> </method> <method name="clamp" qualifiers="const"> @@ -45,56 +53,72 @@ <param index="0" name="min" type="Vector4i" /> <param index="1" name="max" type="Vector4i" /> <description> + Returns a new vector with all components clamped between the components of [param min] and [param max], by running [method @GlobalScope.clamp] on each component. </description> </method> <method name="length" qualifiers="const"> <return type="float" /> <description> + Returns the length (magnitude) of this vector. </description> </method> <method name="length_squared" qualifiers="const"> <return type="int" /> <description> + Returns the squared length (squared magnitude) of this vector. This method runs faster than [method length]. </description> </method> <method name="max_axis_index" qualifiers="const"> <return type="int" /> <description> + Returns the axis of the vector's highest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X]. </description> </method> <method name="min_axis_index" qualifiers="const"> <return type="int" /> <description> + Returns the axis of the vector's lowest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_W]. </description> </method> <method name="sign" qualifiers="const"> <return type="Vector4i" /> <description> + Returns a new vector with each component set to one or negative one, depending on the signs of the components, or zero if the component is zero, by calling [method @GlobalScope.sign] on each component. </description> </method> </methods> <members> <member name="w" type="int" setter="" getter="" default="0"> + The vector's W component. Also accessible by using the index position [code][3][/code]. </member> <member name="x" type="int" setter="" getter="" default="0"> + The vector's X component. Also accessible by using the index position [code][0][/code]. </member> <member name="y" type="int" setter="" getter="" default="0"> + The vector's Y component. Also accessible by using the index position [code][1][/code]. </member> <member name="z" type="int" setter="" getter="" default="0"> + The vector's Z component. Also accessible by using the index position [code][2][/code]. </member> </members> <constants> <constant name="AXIS_X" value="0"> + Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="AXIS_Y" value="1"> + Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="AXIS_Z" value="2"> + Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="AXIS_W" value="3"> + Enumerated value for the W axis. Returned by [method max_axis_index] and [method min_axis_index]. </constant> <constant name="ZERO" value="Vector4i(0, 0, 0, 0)"> + Zero vector, a vector with all components set to [code]0[/code]. </constant> <constant name="ONE" value="Vector4i(1, 1, 1, 1)"> + One vector, a vector with all components set to [code]1[/code]. </constant> </constants> <operators> @@ -102,6 +126,7 @@ <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Returns [code]true[/code] if the vectors are not equal. </description> </operator> <operator name="operator %"> @@ -120,94 +145,130 @@ <return type="Vector4i" /> <param index="0" name="right" type="Vector4i" /> <description> + Multiplies each component of the [Vector4i] by the components of the given [Vector4i]. + [codeblock] + print(Vector4i(10, 20, 30, 40) * Vector4i(3, 4, 5, 6)) # Prints "(30, 80, 150, 240)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector4" /> <param index="0" name="right" type="float" /> <description> + Multiplies each component of the [Vector4i] by the given [float]. + Returns a Vector4 value due to floating-point operations. + [codeblock] + print(Vector4i(10, 20, 30, 40) * 2) # Prints "(20, 40, 60, 80)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector4i" /> <param index="0" name="right" type="int" /> <description> + Multiplies each component of the [Vector4i] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Vector4i" /> <param index="0" name="right" type="Vector4i" /> <description> + Adds each component of the [Vector4i] by the components of the given [Vector4i]. + [codeblock] + print(Vector4i(10, 20, 30, 40) + Vector4i(3, 4, 5, 6)) # Prints "(13, 24, 35, 46)" + [/codeblock] </description> </operator> <operator name="operator -"> <return type="Vector4i" /> <param index="0" name="right" type="Vector4i" /> <description> + Subtracts each component of the [Vector4i] by the components of the given [Vector4i]. + [codeblock] + print(Vector4i(10, 20, 30, 40) - Vector4i(3, 4, 5, 6)) # Prints "(7, 16, 25, 34)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector4i" /> <param index="0" name="right" type="Vector4i" /> <description> + Divides each component of the [Vector4i] by the components of the given [Vector4i]. + [codeblock] + print(Vector4i(10, 20, 30, 40) / Vector4i(2, 5, 3, 4)) # Prints "(5, 4, 10, 10)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector4" /> <param index="0" name="right" type="float" /> <description> + Divides each component of the [Vector4i] by the given [float]. + Returns a Vector4 value due to floating-point operations. + [codeblock] + print(Vector4i(10, 20, 30, 40) / 2 # Prints "(5, 10, 15, 20)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector4i" /> <param index="0" name="right" type="int" /> <description> + Divides each component of the [Vector4i] by the given [int]. </description> </operator> <operator name="operator <"> <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Compares two [Vector4i] vectors by first checking if the X value of the left vector is less than the X value of the [param right] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator <="> <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Compares two [Vector4i] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [param right] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator =="> <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Returns [code]true[/code] if the vectors are exactly equal. </description> </operator> <operator name="operator >"> <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Compares two [Vector4i] vectors by first checking if the X value of the left vector is greater than the X value of the [param right] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator >="> <return type="bool" /> <param index="0" name="right" type="Vector4i" /> <description> + Compares two [Vector4i] vectors by first checking if the X value of the left vector is greater than or equal to the X value of the [param right] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator []"> <return type="int" /> <param index="0" name="index" type="int" /> <description> + Access vector components using their [param index]. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], [code]v[2][/code] is equivalent to [code]v.z[/code], and [code]v[3][/code] is equivalent to [code]v.w[/code]. </description> </operator> <operator name="operator unary+"> <return type="Vector4i" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Vector4i" /> <description> + Returns the negative value of the [Vector4i]. This is the same as writing [code]Vector4i(-v.x, -v.y, -v.z, -v.w)[/code]. This operation flips the direction of the vector while keeping the same magnitude. </description> </operator> </operators> diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index c57412978d..15ae4ffcff 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -711,7 +711,6 @@ void Skeleton3DEditor::create_editors() { ne->add_control_to_menu_panel(skeleton_options); skeleton_options->set_text(TTR("Skeleton3D")); - skeleton_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons"))); // Skeleton options. PopupMenu *p = skeleton_options->get_popup(); @@ -824,7 +823,6 @@ void Skeleton3DEditor::create_editors() { void Skeleton3DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - create_editors(); update_joint_tree(); update_editors(); @@ -844,6 +842,7 @@ void Skeleton3DEditor::_notification(int p_what) { add_theme_constant_override("separation", 0); } break; case NOTIFICATION_THEME_CHANGED: { + skeleton_options->set_icon(get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons"))); edit_mode_button->set_icon(get_theme_icon(SNAME("ToolBoneSelect"), SNAME("EditorIcons"))); key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons"))); key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons"))); @@ -928,6 +927,8 @@ void fragment() { handles_mesh_instance->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF); handles_mesh.instantiate(); handles_mesh_instance->set_mesh(handles_mesh); + + create_editors(); } void Skeleton3DEditor::update_bone_original() { diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index a329c7ee8c..3979cab084 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -5013,17 +5013,24 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } cursor_set_shape(CURSOR_BUSY); - XEvent xevent; + Vector<XEvent> save_events; while (XPending(x11_display) > 0) { + XEvent xevent{ 0 }; XNextEvent(x11_display, &xevent); if (xevent.type == ConfigureNotify) { _window_changed(&xevent); - } else if (xevent.type == MapNotify) { - // Have we failed to set fullscreen while the window was unmapped? - _validate_mode_on_map(main_window); + } else { + // Don't discard this event, we must resend it... + save_events.push_back(xevent); } } + // Resend events that would have been dropped by the early event queue + // processing we just performed. + for (XEvent &ev : save_events) { + XSendEvent(x11_display, ev.xany.window, False, 0, &ev); + } + events_thread.start(_poll_events_thread, this); _update_real_mouse_position(windows[MAIN_WINDOW_ID]); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 268b381029..25c9b33ff9 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -88,6 +88,14 @@ bool SceneTreeTimer::is_process_always() { return process_always; } +void SceneTreeTimer::set_process_in_physics(bool p_process_in_physics) { + process_in_physics = p_process_in_physics; +} + +bool SceneTreeTimer::is_process_in_physics() { + return process_in_physics; +} + void SceneTreeTimer::set_ignore_time_scale(bool p_ignore) { ignore_time_scale = p_ignore; } @@ -420,6 +428,8 @@ bool SceneTree::physics_process(double p_time) { _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack + process_timers(p_time, true); //go through timers + process_tweens(p_time, true); flush_transform_notifications(); @@ -462,37 +472,7 @@ bool SceneTree::process(double p_time) { _flush_delete_queue(); - //go through timers - - List<Ref<SceneTreeTimer>>::Element *L = timers.back(); //last element - - for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) { - List<Ref<SceneTreeTimer>>::Element *N = E->next(); - if (paused && !E->get()->is_process_always()) { - if (E == L) { - break; //break on last, so if new timers were added during list traversal, ignore them. - } - E = N; - continue; - } - - double time_left = E->get()->get_time_left(); - if (E->get()->is_ignore_time_scale()) { - time_left -= Engine::get_singleton()->get_process_step(); - } else { - time_left -= p_time; - } - E->get()->set_time_left(time_left); - - if (time_left <= 0) { - E->get()->emit_signal(SNAME("timeout")); - timers.erase(E); - } - if (E == L) { - break; //break on last, so if new timers were added during list traversal, ignore them. - } - E = N; - } + process_timers(p_time, false); //go through timers process_tweens(p_time, false); @@ -530,6 +510,38 @@ bool SceneTree::process(double p_time) { return _quit; } +void SceneTree::process_timers(float p_delta, bool p_physics_frame) { + List<Ref<SceneTreeTimer>>::Element *L = timers.back(); //last element + + for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) { + List<Ref<SceneTreeTimer>>::Element *N = E->next(); + if ((paused && !E->get()->is_process_always()) || (E->get()->is_process_in_physics() != p_physics_frame)) { + if (E == L) { + break; //break on last, so if new timers were added during list traversal, ignore them. + } + E = N; + continue; + } + + double time_left = E->get()->get_time_left(); + if (E->get()->is_ignore_time_scale()) { + time_left -= Engine::get_singleton()->get_process_step(); + } else { + time_left -= p_delta; + } + E->get()->set_time_left(time_left); + + if (time_left <= 0) { + E->get()->emit_signal(SNAME("timeout")); + timers.erase(E); + } + if (E == L) { + break; //break on last, so if new timers were added during list traversal, ignore them. + } + E = N; + } +} + void SceneTree::process_tweens(float p_delta, bool p_physics) { // This methods works similarly to how SceneTreeTimers are handled. List<Ref<Tween>>::Element *L = tweens.back(); @@ -1157,11 +1169,13 @@ void SceneTree::add_current_scene(Node *p_current) { root->add_child(p_current); } -Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_always) { +Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_always, bool p_process_in_physics, bool p_ignore_time_scale) { Ref<SceneTreeTimer> stt; stt.instantiate(); stt->set_process_always(p_process_always); stt->set_time_left(p_delay_sec); + stt->set_process_in_physics(p_process_in_physics); + stt->set_ignore_time_scale(p_ignore_time_scale); timers.push_back(stt); return stt; } @@ -1259,7 +1273,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); - ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always"), &SceneTree::create_timer, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always", "process_in_physics", "ignore_time_scale"), &SceneTree::create_timer, DEFVAL(true), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("create_tween"), &SceneTree::create_tween); ClassDB::bind_method(D_METHOD("get_processed_tweens"), &SceneTree::get_processed_tweens); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index e66363ab33..45653001ca 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -53,6 +53,7 @@ class SceneTreeTimer : public RefCounted { double time_left = 0.0; bool process_always = true; + bool process_in_physics = false; bool ignore_time_scale = false; protected: @@ -65,6 +66,9 @@ public: void set_process_always(bool p_process_always); bool is_process_always(); + void set_process_in_physics(bool p_process_in_physics); + bool is_process_in_physics(); + void set_ignore_time_scale(bool p_ignore); bool is_ignore_time_scale(); @@ -176,6 +180,7 @@ private: void node_added(Node *p_node); void node_removed(Node *p_node); void node_renamed(Node *p_node); + void process_timers(float p_delta, bool p_physics_frame); void process_tweens(float p_delta, bool p_physics_frame); Group *add_to_group(const StringName &p_group, Node *p_node); @@ -365,7 +370,7 @@ public: Error change_scene_to(const Ref<PackedScene> &p_scene); Error reload_current_scene(); - Ref<SceneTreeTimer> create_timer(double p_delay_sec, bool p_process_always = true); + Ref<SceneTreeTimer> create_timer(double p_delay_sec, bool p_process_always = true, bool p_process_in_physics = false, bool p_ignore_time_scale = false); Ref<Tween> create_tween(); TypedArray<Tween> get_processed_tweens(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 84e4162c00..04f56bb874 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -865,9 +865,7 @@ void Window::_notification(int p_what) { RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); } - // Need to defer here, because theme owner information might be set in - // add_child_notify, which doesn't get called until right after this. - call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); + notification(NOTIFICATION_THEME_CHANGED); } break; case NOTIFICATION_THEME_CHANGED: { |