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(); };