Merge pull request #65698 from KoBeWi/cameraman

Rework how current Camera2D is determined
This commit is contained in:
Rémi Verschelde 2023-01-31 18:56:20 +01:00
commit 14a4408e02
No known key found for this signature in database
GPG key ID: C3336907360768E1
5 changed files with 79 additions and 44 deletions

View file

@ -55,6 +55,18 @@
[b]Note:[/b] The returned value is not the same as [member Node2D.global_position], as it is affected by the drag properties. It is also not the same as the current position if [member position_smoothing_enabled] is [code]true[/code] (see [method get_screen_center_position]).
</description>
</method>
<method name="is_current" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if this [Camera2D] is the active camera (see [method Viewport.get_camera_2d]).
</description>
</method>
<method name="make_current">
<return type="void" />
<description>
Forces this [Camera2D] to become the current active one. [member enabled] must be [code]true[/code].
</description>
</method>
<method name="reset_smoothing">
<return type="void" />
<description>
@ -83,9 +95,6 @@
<member name="anchor_mode" type="int" setter="set_anchor_mode" getter="get_anchor_mode" enum="Camera2D.AnchorMode" default="1">
The Camera2D's anchor point. See [enum AnchorMode] constants.
</member>
<member name="current" type="bool" setter="set_current" getter="is_current" default="false">
If [code]true[/code], the camera acts as the active camera for its [Viewport] ancestor. Only one camera can be current in a given viewport, so setting a different camera in the same viewport [code]current[/code] will disable whatever camera was already active in that viewport.
</member>
<member name="custom_viewport" type="Node" setter="set_custom_viewport" getter="get_custom_viewport">
The custom [Viewport] node attached to the [Camera2D]. If [code]null[/code] or not a [Viewport], uses the default viewport instead.
</member>
@ -124,6 +133,10 @@
<member name="editor_draw_screen" type="bool" setter="set_screen_drawing_enabled" getter="is_screen_drawing_enabled" default="true">
If [code]true[/code], draws the camera's screen rectangle in the editor.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
Controls whether the camera can be active or not. If [code]true[/code], the [Camera2D] will become the main camera when it enters the scene tree and there is no active camera currently (see [method Viewport.get_camera_2d]).
When the camera is currently active and [member enabled] is set to [code]false[/code], the next enabled [Camera2D] in the scene tree will become active.
</member>
<member name="ignore_rotation" type="bool" setter="set_ignore_rotation" getter="is_ignoring_rotation" default="true">
If [code]true[/code], the camera's rendered view is not affected by its [member Node2D.rotation] and [member Node2D.global_rotation].
</member>

View file

@ -50,7 +50,7 @@ void Camera2D::_update_scroll() {
return;
}
if (current) {
if (is_current()) {
ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
Transform2D xform = get_camera_transform();
@ -241,10 +241,6 @@ void Camera2D::_notification(int p_what) {
viewport = get_viewport();
}
if (is_current()) {
viewport->_camera_2d_set(this);
}
canvas = get_canvas();
RID vp = viewport->get_viewport_rid();
@ -254,6 +250,10 @@ void Camera2D::_notification(int p_what) {
add_to_group(group_name);
add_to_group(canvas_group_name);
if (enabled && !viewport->get_camera_2d()) {
make_current();
}
_update_process_callback();
first = true;
_update_scroll();
@ -261,11 +261,7 @@ void Camera2D::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (is_current()) {
if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
viewport->set_canvas_transform(Transform2D());
clear_current();
current = true;
}
clear_current();
}
remove_from_group(group_name);
remove_from_group(canvas_group_name);
@ -397,19 +393,31 @@ void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) {
_update_process_callback();
}
void Camera2D::set_enabled(bool p_enabled) {
enabled = p_enabled;
if (enabled && is_inside_tree() && !viewport->get_camera_2d()) {
make_current();
} else if (!enabled && is_current()) {
clear_current();
}
}
bool Camera2D::is_enabled() const {
return enabled;
}
Camera2D::Camera2DProcessCallback Camera2D::get_process_callback() const {
return process_callback;
}
void Camera2D::_make_current(Object *p_which) {
if (p_which == this) {
current = true;
if (is_inside_tree()) {
get_viewport()->_camera_2d_set(this);
queue_redraw();
}
} else {
current = false;
if (is_inside_tree()) {
if (get_viewport()->get_camera_2d() == this) {
get_viewport()->_camera_2d_set(nullptr);
@ -419,45 +427,34 @@ void Camera2D::_make_current(Object *p_which) {
}
}
void Camera2D::set_current(bool p_current) {
if (p_current) {
make_current();
} else {
if (current) {
clear_current();
}
}
}
void Camera2D::_update_process_internal_for_smoothing() {
bool is_not_in_scene_or_editor = !(is_inside_tree() && Engine::get_singleton()->is_editor_hint());
bool is_any_smoothing_valid = position_smoothing_speed > 0 || rotation_smoothing_speed > 0;
bool enabled = is_any_smoothing_valid && is_not_in_scene_or_editor;
set_process_internal(enabled);
}
bool Camera2D::is_current() const {
return current;
bool enable = is_any_smoothing_valid && is_not_in_scene_or_editor;
set_process_internal(enable);
}
void Camera2D::make_current() {
if (is_inside_tree()) {
get_tree()->call_group(group_name, "_make_current", this);
} else {
current = true;
}
ERR_FAIL_COND(!enabled || !is_inside_tree());
get_tree()->call_group(group_name, "_make_current", this);
_update_scroll();
}
void Camera2D::clear_current() {
if (is_inside_tree()) {
get_tree()->call_group(group_name, "_make_current", (Object *)nullptr);
} else {
current = false;
ERR_FAIL_COND(!is_current());
if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
viewport->assign_next_enabled_camera_2d(group_name);
}
}
bool Camera2D::is_current() const {
if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
return viewport->get_camera_2d() == this;
}
return false;
}
void Camera2D::set_limit(Side p_side, int p_limit) {
ERR_FAIL_INDEX((int)p_side, 4);
limit[p_side] = p_limit;
@ -715,7 +712,10 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &Camera2D::set_process_callback);
ClassDB::bind_method(D_METHOD("get_process_callback"), &Camera2D::get_process_callback);
ClassDB::bind_method(D_METHOD("set_current", "current"), &Camera2D::set_current);
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Camera2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &Camera2D::is_enabled);
ClassDB::bind_method(D_METHOD("make_current"), &Camera2D::make_current);
ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current);
@ -779,7 +779,7 @@ void Camera2D::_bind_methods() {
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 TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");

View file

@ -64,7 +64,7 @@ protected:
Vector2 zoom_scale = Vector2(1, 1);
AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER;
bool ignore_rotation = true;
bool current = false;
bool enabled = true;
real_t position_smoothing_speed = 5.0;
bool follow_smoothing_enabled = false;
@ -88,7 +88,6 @@ protected:
void _update_scroll();
void _make_current(Object *p_which);
void set_current(bool p_current);
void _set_old_smoothing(real_t p_enable);
@ -155,6 +154,9 @@ public:
void set_process_callback(Camera2DProcessCallback p_mode);
Camera2DProcessCallback get_process_callback() const;
void set_enabled(bool p_enabled);
bool is_enabled() const;
void make_current();
void clear_current();
bool is_current() const;

View file

@ -1045,6 +1045,25 @@ Transform2D Viewport::get_final_transform() const {
return _get_input_pre_xform().affine_inverse() * stretch_transform * global_canvas_transform;
}
void Viewport::assign_next_enabled_camera_2d(const StringName &p_camera_group) {
List<Node *> camera_list;
get_tree()->get_nodes_in_group(p_camera_group, &camera_list);
Camera2D *new_camera = nullptr;
for (const Node *E : camera_list) {
const Camera2D *cam = Object::cast_to<Camera2D>(E);
if (cam->is_enabled()) {
new_camera = const_cast<Camera2D *>(cam);
break;
}
}
_camera_2d_set(new_camera);
if (!camera_2d) {
set_canvas_transform(Transform2D());
}
}
void Viewport::_update_canvas_items(Node *p_node) {
if (p_node != this) {
Window *w = Object::cast_to<Window>(p_node);

View file

@ -511,6 +511,7 @@ public:
Transform2D get_global_canvas_transform() const;
Transform2D get_final_transform() const;
void assign_next_enabled_camera_2d(const StringName &p_camera_group);
void gui_set_root_order_dirty();