From 908a392c56f60e8e78d08bfee98e2cc4b0255a95 Mon Sep 17 00:00:00 2001
From: Lazy-Rabbit-2001 <2733679597@qq.com>
Date: Sun, 12 Jan 2025 20:03:52 +0800
Subject: [PATCH] reverted compatibility-breaking changes and added
usability-improving properties.
---
doc/classes/Camera2D.xml | 11 +++++
scene/2d/camera_2d.cpp | 86 ++++++++++++++++++++++++++++++++--------
scene/2d/camera_2d.h | 13 ++++++
3 files changed, 94 insertions(+), 16 deletions(-)
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index da98e6c26a03..aacd64702e3a 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -129,6 +129,9 @@
If [code]true[/code], draws the camera's limits rectangle in the editor.
+
+ If [code]true[/code], draws the camera's limits rectangle in the editor.
+
If [code]true[/code], draws the camera's screen rectangle in the editor.
@@ -145,6 +148,11 @@
Left scroll limit in pixels. The camera stops moving when reaching this value, but [member offset] can push the view past the limit.
+
+ A tool button that snaps the limits to the viewport.
+ In the editor, pressing the button will make [member limit_left] and [member limit_top] become the global position of the camera, and [member limit_right] and [member limit_bottom] become the global position plus the size of the viewport.
+ [b]Readonly:[/b] Since this is a tool button, it is read-only and trying to set the value of this property will trigger an error.
+
Right scroll limit in pixels. The camera stops moving when reaching this value, but [member offset] can push the view past the limit.
@@ -156,6 +164,9 @@
Top scroll limit in pixels. The camera stops moving when reaching this value, but [member offset] can push the view past the limit.
+
+ If [code]true[/code], the camera focus can go anywhere without limits. In this case, the four [code]limit_*[/code] properties will not work.
+
The camera's relative offset. Useful for looking around or camera shake animations. The offsetted camera can go past the limits defined in [member limit_top], [member limit_bottom], [member limit_left] and [member limit_right].
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 975722ea106d..8244a83f9aef 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -48,7 +48,11 @@ void Camera2D::_edit_set_state(const Dictionary &p_state) {
}
void Camera2D::_edit_set_rect(const Rect2 &p_rect) {
+ ERR_FAIL_COND(!limit_unlimited && !_edit_use_rect());
Rect2 rect = p_rect;
+ Vector2 scl = get_global_scale().abs();
+ rect.size *= scl;
+ rect.position = (rect.position + get_global_position()) * scl;
_set_limit_rect(rect);
}
#endif // TOOLS_ENABLED
@@ -56,11 +60,14 @@ void Camera2D::_edit_set_rect(const Rect2 &p_rect) {
#ifdef DEBUG_ENABLED
Rect2 Camera2D::_edit_get_rect() const {
Rect2 rect = _get_limit_rect();
+ Vector2 scl = get_global_scale().abs();
+ rect.size /= scl;
+ rect.position = (rect.position - get_global_position()) / scl;
return rect;
}
bool Camera2D::_edit_use_rect() const {
- return true;
+ return !limit_unlimited;
}
#endif // DEBUG_ENABLED
@@ -200,7 +207,7 @@ Transform2D Camera2D::get_camera_transform() {
Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2());
Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom_scale);
- if (limit_smoothing_enabled) {
+ if (limit_smoothing_enabled && !limit_unlimited) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
camera_pos.x -= screen_rect.position.x - limit[SIDE_LEFT];
}
@@ -253,7 +260,7 @@ Transform2D Camera2D::get_camera_transform() {
Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale);
- if (!position_smoothing_enabled || !limit_smoothing_enabled) {
+ if ((!position_smoothing_enabled || !limit_smoothing_enabled) && !limit_unlimited) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
screen_rect.position.x = limit[SIDE_LEFT];
}
@@ -426,8 +433,7 @@ void Camera2D::_notification(int p_what) {
}
}
- if (limit_drawing_enabled) {
- Color limit_drawing_color(1, 1, 0.25, 0.63);
+ if (limit_drawing_enabled && !limit_unlimited) {
real_t limit_drawing_width = -1;
if (is_current()) {
limit_drawing_width = 3;
@@ -512,6 +518,16 @@ bool Camera2D::is_ignoring_rotation() const {
return ignore_rotation;
}
+void Camera2D::set_limit_unlimited(bool p_limit_unlimited) {
+ limit_unlimited = p_limit_unlimited;
+ _update_scroll();
+ notify_property_list_changed();
+}
+
+bool Camera2D::is_limit_unlimited() const {
+ return limit_unlimited;
+}
+
void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) {
if (process_callback == p_mode) {
return;
@@ -577,19 +593,25 @@ void Camera2D::_update_process_internal_for_smoothing() {
}
void Camera2D::_set_limit_rect(const Rect2 &p_limit_rect) {
- Rect2 limit_rect = p_limit_rect;
- limit_rect.position -= get_global_position();
- Point2 limit_rect_end = limit_rect.get_end();
- limit[SIDE_LEFT] = limit_rect.position.x;
- limit[SIDE_TOP] = limit_rect.position.y;
- limit[SIDE_RIGHT] = limit_rect_end.x;
- limit[SIDE_BOTTOM] = limit_rect_end.y;
+ Point2 limit_rect_end = p_limit_rect.get_end();
+ set_limit(SIDE_LEFT, p_limit_rect.position.x);
+ set_limit(SIDE_TOP, p_limit_rect.position.y);
+ set_limit(SIDE_RIGHT, limit_rect_end.x);
+ set_limit(SIDE_BOTTOM, limit_rect_end.y);
}
Rect2 Camera2D::_get_limit_rect() const {
return Rect2(limit[SIDE_LEFT], limit[SIDE_TOP], limit[SIDE_RIGHT] - limit[SIDE_LEFT], limit[SIDE_BOTTOM] - limit[SIDE_TOP]);
}
+void Camera2D::_set_limit_rect_to_viewport() {
+ Point2 origin = get_global_position();
+ set_limit(SIDE_LEFT, origin.x);
+ set_limit(SIDE_TOP, origin.y);
+ set_limit(SIDE_RIGHT, origin.x + float(GLOBAL_GET("display/window/size/viewport_width")));
+ set_limit(SIDE_BOTTOM, origin.y + float(GLOBAL_GET("display/window/size/viewport_height")));
+}
+
void Camera2D::make_current() {
ERR_FAIL_COND(!enabled || !is_inside_tree());
get_tree()->call_group(group_name, "_make_current", this);
@@ -639,6 +661,14 @@ int Camera2D::get_limit(Side p_side) const {
return limit[p_side];
}
+void Camera2D::set_limit_rect_to_viewport(const Callable &p_limit_rect_to_viewport) {
+ limit_rect_to_viewport = callable_mp(this, &Camera2D::_set_limit_rect_to_viewport);
+}
+
+Callable Camera2D::get_limit_rect_to_viewport() const {
+ return limit_rect_to_viewport;
+}
+
void Camera2D::set_limit_smoothing_enabled(bool enable) {
limit_smoothing_enabled = enable;
_update_scroll();
@@ -858,7 +888,18 @@ bool Camera2D::is_margin_drawing_enabled() const {
return margin_drawing_enabled;
}
+void Camera2D::set_limit_drawing_color(const Color &p_color) {
+ limit_drawing_color = p_color;
+}
+
+Color Camera2D::get_limit_drawing_color() const {
+ return limit_drawing_color;
+}
+
void Camera2D::_validate_property(PropertyInfo &p_property) const {
+ if (limit_unlimited && (p_property.name == "limit_rect_to_viewport" || p_property.name == "limit_smoothed" || p_property.name == "limit_left" || p_property.name == "limit_top" || p_property.name == "limit_right" || p_property.name == "limit_bottom")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
if (!position_smoothing_enabled && p_property.name == "position_smoothing_speed") {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
@@ -889,9 +930,15 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current);
+ ClassDB::bind_method(D_METHOD("set_limit_unlimited", "limit_unlimited"), &Camera2D::set_limit_unlimited);
+ ClassDB::bind_method(D_METHOD("is_limit_unlimited"), &Camera2D::is_limit_unlimited);
+
ClassDB::bind_method(D_METHOD("set_limit", "margin", "limit"), &Camera2D::set_limit);
ClassDB::bind_method(D_METHOD("get_limit", "margin"), &Camera2D::get_limit);
+ ClassDB::bind_method(D_METHOD("set_limit_rect_to_viewport", "limit_rect_to_viewport"), &Camera2D::set_limit_rect_to_viewport);
+ ClassDB::bind_method(D_METHOD("get_limit_rect_to_viewport"), &Camera2D::get_limit_rect_to_viewport);
+
ClassDB::bind_method(D_METHOD("set_limit_smoothing_enabled", "limit_smoothing_enabled"), &Camera2D::set_limit_smoothing_enabled);
ClassDB::bind_method(D_METHOD("is_limit_smoothing_enabled"), &Camera2D::is_limit_smoothing_enabled);
@@ -946,6 +993,9 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin_drawing_enabled", "margin_drawing_enabled"), &Camera2D::set_margin_drawing_enabled);
ClassDB::bind_method(D_METHOD("is_margin_drawing_enabled"), &Camera2D::is_margin_drawing_enabled);
+ ClassDB::bind_method(D_METHOD("set_limit_drawing_color", "limit_drawing_color"), &Camera2D::set_limit_drawing_color);
+ ClassDB::bind_method(D_METHOD("get_limit_drawing_color"), &Camera2D::get_limit_drawing_color);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed Top Left,Drag Center"), "set_anchor_mode", "get_anchor_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation");
@@ -955,10 +1005,12 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
ADD_GROUP("Limit", "limit_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_unlimited"), "set_limit_unlimited", "is_limit_unlimited");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_LEFT);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_top", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_right", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_RIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_BOTTOM);
+ ADD_PROPERTY(PropertyInfo(Variant::CALLABLE, "limit_rect_to_viewport", PROPERTY_HINT_TOOL_BUTTON, "Snap Limit to Viewport"), "", "get_limit_rect_to_viewport");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_smoothed"), "set_limit_smoothing_enabled", "is_limit_smoothing_enabled");
ADD_GROUP("Position Smoothing", "position_smoothing_");
@@ -982,6 +1034,7 @@ void Camera2D::_bind_methods() {
ADD_GROUP("Editor", "editor_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_screen"), "set_screen_drawing_enabled", "is_screen_drawing_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_limits"), "set_limit_drawing_enabled", "is_limit_drawing_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "editor_draw_limits_color"), "set_limit_rect_to_viewport", "get_limit_rect_to_viewport");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_drag_margin"), "set_margin_drawing_enabled", "is_margin_drawing_enabled");
BIND_ENUM_CONSTANT(ANCHOR_MODE_FIXED_TOP_LEFT);
@@ -991,10 +1044,11 @@ void Camera2D::_bind_methods() {
}
Camera2D::Camera2D() {
- limit[SIDE_LEFT] = 0;
- limit[SIDE_TOP] = 0;
- limit[SIDE_RIGHT] = GLOBAL_GET("display/window/size/viewport_width");
- limit[SIDE_BOTTOM] = GLOBAL_GET("display/window/size/viewport_height");
+ limit[SIDE_LEFT] = -10000000;
+ limit[SIDE_TOP] = -10000000;
+ limit[SIDE_RIGHT] = 10000000;
+ limit[SIDE_BOTTOM] = 10000000;
+ limit_rect_to_viewport = callable_mp(this, &Camera2D::_set_limit_rect_to_viewport);
drag_margin[SIDE_LEFT] = 0.2;
drag_margin[SIDE_TOP] = 0.2;
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 912bf2c67d54..3bd5afd4b2b8 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -73,8 +73,10 @@ class Camera2D : public Node2D {
real_t rotation_smoothing_speed = 5.0;
bool rotation_smoothing_enabled = false;
+ bool limit_unlimited = true;
int limit[4];
bool limit_smoothing_enabled = false;
+ Callable limit_rect_to_viewport;
real_t drag_margin[4];
bool drag_horizontal_enabled = false;
@@ -101,10 +103,12 @@ class Camera2D : public Node2D {
void _set_limit_rect(const Rect2 &p_limit_rect);
Rect2 _get_limit_rect() const;
+ void _set_limit_rect_to_viewport();
bool screen_drawing_enabled = true;
bool limit_drawing_enabled = false;
bool margin_drawing_enabled = false;
+ Color limit_drawing_color = Color(1, 1, 0.25, 0.63);
Camera2DProcessCallback process_callback = CAMERA2D_PROCESS_IDLE;
@@ -151,9 +155,15 @@ class Camera2D : public Node2D {
void set_ignore_rotation(bool p_ignore);
bool is_ignoring_rotation() const;
+ void set_limit_unlimited(bool p_limit_unlimited);
+ bool is_limit_unlimited() const;
+
void set_limit(Side p_side, int p_limit);
int get_limit(Side p_side) const;
+ void set_limit_rect_to_viewport(const Callable &p_limit_rect_to_viewport);
+ Callable get_limit_rect_to_viewport() const;
+
void set_limit_smoothing_enabled(bool enable);
bool is_limit_smoothing_enabled() const;
@@ -216,6 +226,9 @@ class Camera2D : public Node2D {
void set_margin_drawing_enabled(bool enable);
bool is_margin_drawing_enabled() const;
+ void set_limit_drawing_color(const Color &p_color);
+ Color get_limit_drawing_color() const;
+
Camera2D();
};