Fixed Timestep Interpolation (2D)

Adds fixed timestep interpolation to the rendering server (2D only).
Switchable on and off with a project setting (default is off).

Co-authored-by: lawnjelly <lawnjelly@gmail.com>
This commit is contained in:
Ricardo Buring
2024-02-17 00:57:32 +01:00
parent fe01776f05
commit 2ed2ccc2d8
39 changed files with 1040 additions and 75 deletions

View File

@@ -66,7 +66,9 @@ protected:
};
public:
enum ProcessMode {
// N.B. Any enum stored as a bitfield should be specified as UNSIGNED to work around
// some compilers trying to store it as signed, and requiring 1 more bit than necessary.
enum ProcessMode : unsigned int {
PROCESS_MODE_INHERIT, // same as parent node
PROCESS_MODE_PAUSABLE, // process only if not paused
PROCESS_MODE_WHEN_PAUSED, // process only if paused
@@ -86,6 +88,12 @@ public:
FLAG_PROCESS_THREAD_MESSAGES_ALL = 3,
};
enum PhysicsInterpolationMode : unsigned int {
PHYSICS_INTERPOLATION_MODE_INHERIT,
PHYSICS_INTERPOLATION_MODE_ON,
PHYSICS_INTERPOLATION_MODE_OFF,
};
enum DuplicateFlags {
DUPLICATE_SIGNALS = 1,
DUPLICATE_GROUPS = 2,
@@ -170,9 +178,7 @@ private:
int blocked = 0; // Safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed.
StringName name;
SceneTree *tree = nullptr;
bool inside_tree = false;
bool ready_notified = false; // This is a small hack, so if a node is added during _ready() to the tree, it correctly gets the _ready() notification.
bool ready_first = true;
#ifdef TOOLS_ENABLED
NodePath import_path; // Path used when imported, used by scene editors to keep tracking.
#endif
@@ -184,7 +190,6 @@ private:
List<Node *>::Element *OW = nullptr; // Owned element.
List<Node *> owned;
ProcessMode process_mode = PROCESS_MODE_INHERIT;
Node *process_owner = nullptr;
ProcessThreadGroup process_thread_group = PROCESS_THREAD_GROUP_INHERIT;
Node *process_thread_group_owner = nullptr;
@@ -196,26 +201,39 @@ private:
Variant rpc_config;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
bool physics_process = false;
bool process = false;
int process_priority = 0;
int physics_process_priority = 0;
bool physics_process_internal = false;
bool process_internal = false;
// Keep bitpacked values together to get better packing.
ProcessMode process_mode : 3;
PhysicsInterpolationMode physics_interpolation_mode : 2;
bool input = false;
bool shortcut_input = false;
bool unhandled_input = false;
bool unhandled_key_input = false;
bool physics_process : 1;
bool process : 1;
bool parent_owned = false;
bool in_constructor = true;
bool use_placeholder = false;
bool physics_process_internal : 1;
bool process_internal : 1;
bool display_folded = false;
bool editable_instance = false;
bool input : 1;
bool shortcut_input : 1;
bool unhandled_input : 1;
bool unhandled_key_input : 1;
// Physics interpolation can be turned on and off on a per node basis.
// This only takes effect when the SceneTree (or project setting) physics interpolation
// is switched on.
bool physics_interpolated : 1;
bool parent_owned : 1;
bool in_constructor : 1;
bool use_placeholder : 1;
bool display_folded : 1;
bool editable_instance : 1;
bool inside_tree : 1;
bool ready_notified : 1;
bool ready_first : 1;
AutoTranslateMode auto_translate_mode = AUTO_TRANSLATE_MODE_INHERIT;
mutable bool is_auto_translating = true;
@@ -243,6 +261,7 @@ private:
void _propagate_ready();
void _propagate_exit_tree();
void _propagate_after_exit_tree();
void _propagate_physics_interpolated(bool p_interpolated);
void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification);
void _propagate_groups_dirty();
Array _get_node_and_resource(const NodePath &p_path);
@@ -295,6 +314,8 @@ protected:
void _notification(int p_notification);
virtual void _physics_interpolated_changed();
virtual void add_child_notify(Node *p_child);
virtual void remove_child_notify(Node *p_child);
virtual void move_child_notify(Node *p_child);
@@ -339,7 +360,7 @@ protected:
public:
enum {
// you can make your own, but don't use the same numbers as other notifications in other nodes
// You can make your own, but don't use the same numbers as other notifications in other nodes.
NOTIFICATION_ENTER_TREE = 10,
NOTIFICATION_EXIT_TREE = 11,
NOTIFICATION_MOVED_IN_PARENT = 12,
@@ -360,8 +381,8 @@ public:
NOTIFICATION_POST_ENTER_TREE = 27,
NOTIFICATION_DISABLED = 28,
NOTIFICATION_ENABLED = 29,
//keep these linked to node
NOTIFICATION_RESET_PHYSICS_INTERPOLATION = 2001, // A GodotSpace Odyssey.
// Keep these linked to Node.
NOTIFICATION_WM_MOUSE_ENTER = 1002,
NOTIFICATION_WM_MOUSE_EXIT = 1003,
NOTIFICATION_WM_WINDOW_FOCUS_IN = 1004,
@@ -613,6 +634,13 @@ public:
ProcessMode get_process_mode() const;
bool can_process() const;
bool can_process_notification(int p_what) const;
void set_physics_interpolation_mode(PhysicsInterpolationMode p_mode);
PhysicsInterpolationMode get_physics_interpolation_mode() const { return data.physics_interpolation_mode; }
_FORCE_INLINE_ bool is_physics_interpolated() const { return data.physics_interpolated; }
_FORCE_INLINE_ bool is_physics_interpolated_and_enabled() const { return is_inside_tree() && get_tree()->is_physics_interpolation_enabled() && is_physics_interpolated(); }
void reset_physics_interpolation();
bool is_enabled() const;
bool is_ready() const;
@@ -742,6 +770,7 @@ VARIANT_ENUM_CAST(Node::ProcessMode);
VARIANT_ENUM_CAST(Node::ProcessThreadGroup);
VARIANT_BITFIELD_CAST(Node::ProcessThreadMessages);
VARIANT_ENUM_CAST(Node::InternalMode);
VARIANT_ENUM_CAST(Node::PhysicsInterpolationMode);
VARIANT_ENUM_CAST(Node::AutoTranslateMode);
typedef HashSet<Node *, Node::Comparator> NodeSet;