summaryrefslogtreecommitdiffstats
path: root/scene/2d/camera_2d.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/camera_2d.cpp')
-rw-r--r--scene/2d/camera_2d.cpp107
1 files changed, 91 insertions, 16 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 722858b674..e9bab274c6 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -54,7 +54,12 @@ void Camera2D::_update_scroll() {
if (is_current()) {
ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
- Transform2D xform = get_camera_transform();
+ Transform2D xform;
+ if (is_physics_interpolated_and_enabled()) {
+ xform = _interpolation_data.xform_prev.interpolate_with(_interpolation_data.xform_curr, Engine::get_singleton()->get_physics_interpolation_fraction());
+ } else {
+ xform = get_camera_transform();
+ }
viewport->set_canvas_transform(xform);
@@ -68,15 +73,26 @@ void Camera2D::_update_scroll() {
}
void Camera2D::_update_process_callback() {
- if (_is_editing_in_editor()) {
+ if (is_physics_interpolated_and_enabled()) {
+ set_process_internal(is_current());
+ set_physics_process_internal(is_current());
+
+#ifdef TOOLS_ENABLED
+ if (process_callback == CAMERA2D_PROCESS_IDLE) {
+ WARN_PRINT_ONCE("Camera2D overridden to physics process mode due to use of physics interpolation.");
+ }
+#endif
+ } else if (_is_editing_in_editor()) {
set_process_internal(false);
set_physics_process_internal(false);
- } else if (process_callback == CAMERA2D_PROCESS_IDLE) {
- set_process_internal(true);
- set_physics_process_internal(false);
} else {
- set_process_internal(false);
- set_physics_process_internal(true);
+ if (process_callback == CAMERA2D_PROCESS_IDLE) {
+ set_process_internal(true);
+ set_physics_process_internal(false);
+ } else {
+ set_process_internal(false);
+ set_physics_process_internal(true);
+ }
}
}
@@ -161,8 +177,15 @@ Transform2D Camera2D::get_camera_transform() {
}
}
+ // FIXME: There is a bug here, introduced before physics interpolation.
+ // Smoothing occurs rather confusingly during the call to get_camera_transform().
+ // It may be called MULTIPLE TIMES on certain frames,
+ // therefore smoothing is not currently applied only once per frame / tick,
+ // which will result in some haphazard results.
if (position_smoothing_enabled && !_is_editing_in_editor()) {
- real_t c = position_smoothing_speed * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
+ bool physics_process = (process_callback == CAMERA2D_PROCESS_PHYSICS) || is_physics_interpolated_and_enabled();
+ real_t delta = physics_process ? get_physics_process_delta_time() : get_process_delta_time();
+ real_t c = position_smoothing_speed * delta;
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
ret_camera_pos = smoothed_camera_pos;
//camera_pos=camera_pos*(1.0-position_smoothing_speed)+new_camera_pos*position_smoothing_speed;
@@ -223,17 +246,52 @@ Transform2D Camera2D::get_camera_transform() {
return xform.affine_inverse();
}
+void Camera2D::_ensure_update_interpolation_data() {
+ // The "curr -> previous" update can either occur
+ // on NOTIFICATION_INTERNAL_PHYSICS_PROCESS, OR
+ // on NOTIFICATION_TRANSFORM_CHANGED,
+ // if NOTIFICATION_TRANSFORM_CHANGED takes place earlier than
+ // NOTIFICATION_INTERNAL_PHYSICS_PROCESS on a tick.
+ // This is to ensure that the data keeps flowing, but the new data
+ // doesn't overwrite before prev has been set.
+
+ // Keep the data flowing.
+ uint64_t tick = Engine::get_singleton()->get_physics_frames();
+ if (_interpolation_data.last_update_physics_tick != tick) {
+ _interpolation_data.xform_prev = _interpolation_data.xform_curr;
+ _interpolation_data.last_update_physics_tick = tick;
+ }
+}
+
void Camera2D::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_INTERNAL_PROCESS:
- case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ case NOTIFICATION_INTERNAL_PROCESS: {
_update_scroll();
} break;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (is_physics_interpolated_and_enabled()) {
+ _ensure_update_interpolation_data();
+ _interpolation_data.xform_curr = get_camera_transform();
+ } else {
+ _update_scroll();
+ }
+ } break;
+
+ case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
+ // Force the limits etc. to update.
+ _interpolation_data.xform_curr = get_camera_transform();
+ _interpolation_data.xform_prev = _interpolation_data.xform_curr;
+ } break;
+
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!position_smoothing_enabled || _is_editing_in_editor()) {
+ if ((!position_smoothing_enabled && !is_physics_interpolated_and_enabled()) || _is_editing_in_editor()) {
_update_scroll();
}
+ if (is_physics_interpolated_and_enabled()) {
+ _ensure_update_interpolation_data();
+ _interpolation_data.xform_curr = get_camera_transform();
+ }
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -260,6 +318,15 @@ void Camera2D::_notification(int p_what) {
_update_process_callback();
first = true;
_update_scroll();
+
+ // Note that NOTIFICATION_RESET_PHYSICS_INTERPOLATION
+ // is automatically called before this because Camera2D is inherited
+ // from CanvasItem. However, the camera transform is not up to date
+ // until this point, so we do an extra manual reset.
+ if (is_physics_interpolated_and_enabled()) {
+ _interpolation_data.xform_curr = get_camera_transform();
+ _interpolation_data.xform_prev = _interpolation_data.xform_curr;
+ }
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -431,12 +498,17 @@ void Camera2D::_make_current(Object *p_which) {
queue_redraw();
- if (p_which == this) {
+ bool was_current = viewport->get_camera_2d() == this;
+ bool is_current = p_which == this;
+
+ if (is_current) {
viewport->_camera_2d_set(this);
- } else {
- if (viewport->get_camera_2d() == this) {
- viewport->_camera_2d_set(nullptr);
- }
+ } else if (was_current) {
+ viewport->_camera_2d_set(nullptr);
+ }
+
+ if (is_current != was_current) {
+ _update_process_callback();
}
}
@@ -456,6 +528,7 @@ void Camera2D::make_current() {
_make_current(this);
}
_update_scroll();
+ _update_process_callback();
}
void Camera2D::clear_current() {
@@ -468,6 +541,8 @@ void Camera2D::clear_current() {
if (!custom_viewport || ObjectDB::get_instance(custom_viewport_id)) {
viewport->assign_next_enabled_camera_2d(group_name);
}
+
+ _update_process_callback();
}
bool Camera2D::is_current() const {