Skip to content

Commit

Permalink
2d camera defer_scroll option
Browse files Browse the repository at this point in the history
2d cameras currently often give a frame delay between moving the camera and see the effects being updated.

This PR adds an option to use a more optimized scroll_update (guaranteed no more than 1 per frame) which occurs after all other scene tree updates, removing the frame delay.
  • Loading branch information
lawnjelly committed Mar 1, 2021
1 parent 7e2e96c commit 7fe9aeb
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
46 changes: 43 additions & 3 deletions scene/2d/camera_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,24 @@
#include "scene/scene_string_names.h"
#include "servers/visual_server.h"

LocalVector<ObjectID> Camera2D::_pending_scroll_cameras;

void Camera2D::flush_pending_scrolls() {
for (unsigned int n = 0; n < _pending_scroll_cameras.size(); n++) {
Camera2D *cam = Object::cast_to<Camera2D>(ObjectDB::get_instance(_pending_scroll_cameras[n]));

if (cam && cam->scroll_dirty) {
cam->_update_scroll();
}
}

_pending_scroll_cameras.clear();
}

void Camera2D::_update_scroll() {

scroll_dirty = false;

if (!is_inside_tree())
return;

Expand Down Expand Up @@ -226,13 +242,23 @@ void Camera2D::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS:
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {

_update_scroll();
// we can potentially switch off internal process if deferring scroll update? NYI
if (!defer_scroll_enabled) {
_update_scroll();
}

} break;
case NOTIFICATION_TRANSFORM_CHANGED: {

if (!is_processing_internal() && !is_physics_processing_internal())
_update_scroll();
if (defer_scroll_enabled) {
if (!scroll_dirty) {
scroll_dirty = true;
_pending_scroll_cameras.push_back(get_instance_id());
}
} else {
if (!is_processing_internal() && !is_physics_processing_internal())
_update_scroll();
}

} break;
case NOTIFICATION_ENTER_TREE: {
Expand Down Expand Up @@ -401,6 +427,14 @@ Camera2D::Camera2DProcessMode Camera2D::get_process_mode() const {
return process_mode;
}

void Camera2D::set_defer_scroll_enabled(bool p_enable) {
defer_scroll_enabled = p_enable;
}

bool Camera2D::get_defer_scroll_enabled() const {
return defer_scroll_enabled;
}

void Camera2D::_make_current(Object *p_which) {

if (p_which == this) {
Expand Down Expand Up @@ -689,6 +723,9 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Camera2D::set_process_mode);
ClassDB::bind_method(D_METHOD("get_process_mode"), &Camera2D::get_process_mode);

ClassDB::bind_method(D_METHOD("set_defer_scroll_enabled", "enabled"), &Camera2D::set_defer_scroll_enabled);
ClassDB::bind_method(D_METHOD("get_defer_scroll_enabled"), &Camera2D::get_defer_scroll_enabled);

ClassDB::bind_method(D_METHOD("_set_current", "current"), &Camera2D::_set_current);
ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);

Expand Down Expand Up @@ -750,6 +787,7 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "defer_scroll"), "set_defer_scroll_enabled", "get_defer_scroll_enabled");

ADD_GROUP("Limit", "limit_");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left"), "set_limit", "get_limit", MARGIN_LEFT);
Expand Down Expand Up @@ -808,6 +846,8 @@ Camera2D::Camera2D() {
custom_viewport = NULL;
custom_viewport_id = 0;
process_mode = CAMERA2D_PROCESS_IDLE;
defer_scroll_enabled = true;
scroll_dirty = true;

smoothing = 5.0;
zoom = Vector2(1, 1);
Expand Down
12 changes: 12 additions & 0 deletions scene/2d/camera_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#ifndef CAMERA_2D_H
#define CAMERA_2D_H

#include "core/local_vector.h"
#include "scene/2d/node_2d.h"
#include "scene/main/viewport.h"

Expand Down Expand Up @@ -94,6 +95,9 @@ class Camera2D : public Node2D {
bool margin_drawing_enabled;

Camera2DProcessMode process_mode;
bool defer_scroll_enabled;

bool scroll_dirty;

protected:
virtual Transform2D get_camera_transform();
Expand Down Expand Up @@ -140,6 +144,9 @@ class Camera2D : public Node2D {
void set_process_mode(Camera2DProcessMode p_mode);
Camera2DProcessMode get_process_mode() const;

void set_defer_scroll_enabled(bool p_enable);
bool get_defer_scroll_enabled() const;

void make_current();
void clear_current();
bool is_current() const;
Expand Down Expand Up @@ -167,6 +174,11 @@ class Camera2D : public Node2D {
bool is_margin_drawing_enabled() const;

Camera2D();

static void flush_pending_scrolls();

private:
static LocalVector<ObjectID> _pending_scroll_cameras;
};

VARIANT_ENUM_CAST(Camera2D::AnchorMode);
Expand Down
7 changes: 7 additions & 0 deletions scene/main/scene_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "core/project_settings.h"
#include "main/input_default.h"
#include "node.h"
#include "scene/2d/camera_2d.h"
#include "scene/debugger/script_debugger_remote.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/material.h"
Expand Down Expand Up @@ -576,6 +577,12 @@ bool SceneTree::idle(float p_time) {

flush_transform_notifications(); //additional transforms after timers update

// flush pending camera scrolls
Camera2D::flush_pending_scrolls();

// any further transform notifications
flush_transform_notifications();

_call_idle_callbacks();

#ifdef TOOLS_ENABLED
Expand Down

0 comments on commit 7fe9aeb

Please sign in to comment.