feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -32,8 +32,12 @@
|
|||
|
||||
#include "container.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/translation_server.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/panel.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
#include "scene/main/canvas_layer.h"
|
||||
#include "scene/main/window.h"
|
||||
|
|
@ -56,18 +60,10 @@ Dictionary Control::_edit_get_state() const {
|
|||
s["scale"] = get_scale();
|
||||
s["pivot"] = get_pivot_offset();
|
||||
|
||||
Array anchors;
|
||||
anchors.push_back(get_anchor(SIDE_LEFT));
|
||||
anchors.push_back(get_anchor(SIDE_TOP));
|
||||
anchors.push_back(get_anchor(SIDE_RIGHT));
|
||||
anchors.push_back(get_anchor(SIDE_BOTTOM));
|
||||
Array anchors = { get_anchor(SIDE_LEFT), get_anchor(SIDE_TOP), get_anchor(SIDE_RIGHT), get_anchor(SIDE_BOTTOM) };
|
||||
s["anchors"] = anchors;
|
||||
|
||||
Array offsets;
|
||||
offsets.push_back(get_offset(SIDE_LEFT));
|
||||
offsets.push_back(get_offset(SIDE_TOP));
|
||||
offsets.push_back(get_offset(SIDE_RIGHT));
|
||||
offsets.push_back(get_offset(SIDE_BOTTOM));
|
||||
Array offsets = { get_offset(SIDE_LEFT), get_offset(SIDE_TOP), get_offset(SIDE_RIGHT), get_offset(SIDE_BOTTOM) };
|
||||
s["offsets"] = offsets;
|
||||
|
||||
s["layout_mode"] = _get_layout_mode();
|
||||
|
|
@ -254,6 +250,27 @@ PackedStringArray Control::get_configuration_warnings() const {
|
|||
return warnings;
|
||||
}
|
||||
|
||||
PackedStringArray Control::get_accessibility_configuration_warnings() const {
|
||||
ERR_READ_THREAD_GUARD_V(PackedStringArray());
|
||||
PackedStringArray warnings = Node::get_accessibility_configuration_warnings();
|
||||
|
||||
String ac_name = get_accessibility_name().strip_edges();
|
||||
if (ac_name.is_empty()) {
|
||||
warnings.push_back(RTR("Accessibility Name must not be empty, or contain only spaces."));
|
||||
}
|
||||
if (ac_name.contains(get_class_name())) {
|
||||
warnings.push_back(RTR("Accessibility Name must not include Node class name."));
|
||||
}
|
||||
for (int i = 0; i < ac_name.length(); i++) {
|
||||
if (is_control(ac_name[i])) {
|
||||
warnings.push_back(RTR("Accessibility Name must not include control character."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
bool Control::is_text_field() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return false;
|
||||
|
|
@ -481,9 +498,9 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
}
|
||||
|
||||
// Validate which positioning properties should be displayed depending on the parent and the layout mode.
|
||||
Node *parent_node = get_parent_control();
|
||||
if (!parent_node) {
|
||||
// If there is no parent, display both anchor and container options.
|
||||
Control *parent_control = get_parent_control();
|
||||
if (!parent_control) {
|
||||
// If there is no parent control, display both anchor and container options.
|
||||
|
||||
// Set the layout mode to be disabled with the proper value.
|
||||
if (p_property.name == "layout_mode") {
|
||||
|
|
@ -496,7 +513,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
if (!use_custom_anchors && (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_"))) {
|
||||
p_property.usage ^= PROPERTY_USAGE_EDITOR;
|
||||
}
|
||||
} else if (Object::cast_to<Container>(parent_node)) {
|
||||
} else if (Object::cast_to<Container>(parent_control)) {
|
||||
// If the parent is a container, display only container-related properties.
|
||||
if (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset") {
|
||||
p_property.usage ^= PROPERTY_USAGE_DEFAULT;
|
||||
|
|
@ -508,7 +525,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
p_property.usage |= PROPERTY_USAGE_READ_ONLY;
|
||||
} else if (p_property.name == "size_flags_horizontal" || p_property.name == "size_flags_vertical") {
|
||||
// Filter allowed size flags based on the parent container configuration.
|
||||
Container *parent_container = Object::cast_to<Container>(parent_node);
|
||||
Container *parent_container = Object::cast_to<Container>(parent_control);
|
||||
Vector<int> size_flags;
|
||||
if (p_property.name == "size_flags_horizontal") {
|
||||
size_flags = parent_container->get_allowed_size_flags_horizontal();
|
||||
|
|
@ -548,7 +565,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// If the parent is NOT a container or not a control at all, display only anchoring-related properties.
|
||||
// If the parent is a non-container control, display only anchoring-related properties.
|
||||
if (p_property.name.begins_with("size_flags_")) {
|
||||
p_property.usage ^= PROPERTY_USAGE_EDITOR;
|
||||
|
||||
|
|
@ -570,7 +587,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
}
|
||||
|
||||
// Disable the property if it's managed by the parent container.
|
||||
if (!Object::cast_to<Container>(parent_node)) {
|
||||
if (!Object::cast_to<Container>(parent_control)) {
|
||||
return;
|
||||
}
|
||||
bool property_is_managed_by_container = false;
|
||||
|
|
@ -607,11 +624,6 @@ bool Control::_property_get_revert(const StringName &p_name, Variant &r_property
|
|||
|
||||
// Global relations.
|
||||
|
||||
bool Control::is_top_level_control() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_top_level());
|
||||
}
|
||||
|
||||
Control *Control::get_parent_control() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
return data.parent_control;
|
||||
|
|
@ -631,10 +643,6 @@ Control *Control::get_root_parent_control() const {
|
|||
const Control *c = Object::cast_to<Control>(ci);
|
||||
if (c) {
|
||||
root = c;
|
||||
|
||||
if (c->data.RI || c->is_top_level_control()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ci = ci->get_parent_item();
|
||||
|
|
@ -875,6 +883,13 @@ void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (
|
|||
r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
|
||||
}
|
||||
|
||||
void Control::_compute_edge_positions(Rect2 p_rect, real_t (&r_edge_positions)[4]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t area = p_rect.size[i & 1];
|
||||
r_edge_positions[i] = data.offset[i] + (data.anchor[i] * area);
|
||||
}
|
||||
}
|
||||
|
||||
/// Presets and layout modes.
|
||||
|
||||
void Control::_set_layout_mode(LayoutMode p_mode) {
|
||||
|
|
@ -905,11 +920,11 @@ void Control::_update_layout_mode() {
|
|||
}
|
||||
|
||||
Control::LayoutMode Control::_get_layout_mode() const {
|
||||
Node *parent_node = get_parent_control();
|
||||
Control *parent_control = get_parent_control();
|
||||
// In these modes the property is read-only.
|
||||
if (!parent_node) {
|
||||
if (!parent_control) {
|
||||
return LayoutMode::LAYOUT_MODE_UNCONTROLLED;
|
||||
} else if (Object::cast_to<Container>(parent_node)) {
|
||||
} else if (Object::cast_to<Container>(parent_control)) {
|
||||
return LayoutMode::LAYOUT_MODE_CONTAINER;
|
||||
}
|
||||
|
||||
|
|
@ -918,20 +933,25 @@ Control::LayoutMode Control::_get_layout_mode() const {
|
|||
return LayoutMode::LAYOUT_MODE_ANCHORS;
|
||||
}
|
||||
|
||||
// Otherwise fallback on what's stored.
|
||||
return data.stored_layout_mode;
|
||||
// Only position/anchors modes are valid for non-container control parent.
|
||||
if (data.stored_layout_mode == LayoutMode::LAYOUT_MODE_POSITION || data.stored_layout_mode == LayoutMode::LAYOUT_MODE_ANCHORS) {
|
||||
return data.stored_layout_mode;
|
||||
}
|
||||
|
||||
// Otherwise fallback to position mode.
|
||||
return LayoutMode::LAYOUT_MODE_POSITION;
|
||||
}
|
||||
|
||||
Control::LayoutMode Control::_get_default_layout_mode() const {
|
||||
Node *parent_node = get_parent_control();
|
||||
Control *parent_control = get_parent_control();
|
||||
// In these modes the property is read-only.
|
||||
if (!parent_node) {
|
||||
if (!parent_control) {
|
||||
return LayoutMode::LAYOUT_MODE_UNCONTROLLED;
|
||||
} else if (Object::cast_to<Container>(parent_node)) {
|
||||
} else if (Object::cast_to<Container>(parent_control)) {
|
||||
return LayoutMode::LAYOUT_MODE_CONTAINER;
|
||||
}
|
||||
|
||||
// Otherwise fallback on the position mode.
|
||||
// Otherwise fallback to the position mode.
|
||||
return LayoutMode::LAYOUT_MODE_POSITION;
|
||||
}
|
||||
|
||||
|
|
@ -1400,10 +1420,13 @@ void Control::set_position(const Point2 &p_point, bool p_keep_offsets) {
|
|||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
real_t edge_pos[4];
|
||||
_compute_edge_positions(get_parent_anchorable_rect(), edge_pos);
|
||||
Size2 offset_size(edge_pos[2] - edge_pos[0], edge_pos[3] - edge_pos[1]);
|
||||
if (p_keep_offsets) {
|
||||
_compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
|
||||
_compute_anchors(Rect2(p_point, offset_size), data.offset, data.anchor);
|
||||
} else {
|
||||
_compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
|
||||
_compute_offsets(Rect2(p_point, offset_size), data.anchor, data.offset);
|
||||
}
|
||||
_size_changed();
|
||||
}
|
||||
|
|
@ -1537,6 +1560,7 @@ void Control::set_scale(const Vector2 &p_scale) {
|
|||
}
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_scale() const {
|
||||
|
|
@ -1553,6 +1577,7 @@ void Control::set_rotation(real_t p_radians) {
|
|||
data.rotation = p_radians;
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
void Control::set_rotation_degrees(real_t p_degrees) {
|
||||
|
|
@ -1579,6 +1604,7 @@ void Control::set_pivot_offset(const Vector2 &p_pivot) {
|
|||
data.pivot_offset = p_pivot;
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_pivot_offset() const {
|
||||
|
|
@ -1690,14 +1716,8 @@ Size2 Control::get_combined_minimum_size() const {
|
|||
|
||||
void Control::_size_changed() {
|
||||
Rect2 parent_rect = get_parent_anchorable_rect();
|
||||
|
||||
real_t edge_pos[4];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t area = parent_rect.size[i & 1];
|
||||
edge_pos[i] = data.offset[i] + (data.anchor[i] * area);
|
||||
}
|
||||
|
||||
_compute_edge_positions(parent_rect, edge_pos);
|
||||
Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]);
|
||||
Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache;
|
||||
|
||||
|
|
@ -1727,8 +1747,11 @@ void Control::_size_changed() {
|
|||
new_size_cache.height = minimum_size.height;
|
||||
}
|
||||
|
||||
bool pos_changed = !new_pos_cache.is_equal_approx(data.pos_cache);
|
||||
bool size_changed = !new_size_cache.is_equal_approx(data.size_cache);
|
||||
bool pos_changed = new_pos_cache != data.pos_cache;
|
||||
bool size_changed = new_size_cache != data.size_cache;
|
||||
// Below helps in getting rid of floating point errors for signaling resized.
|
||||
bool approx_pos_changed = !new_pos_cache.is_equal_approx(data.pos_cache);
|
||||
bool approx_size_changed = !new_size_cache.is_equal_approx(data.size_cache);
|
||||
|
||||
if (pos_changed) {
|
||||
data.pos_cache = new_pos_cache;
|
||||
|
|
@ -1738,13 +1761,13 @@ void Control::_size_changed() {
|
|||
}
|
||||
|
||||
if (is_inside_tree()) {
|
||||
if (pos_changed || size_changed) {
|
||||
if (approx_pos_changed || approx_size_changed) {
|
||||
// Ensure global transform is marked as dirty before `NOTIFICATION_RESIZED` / `item_rect_changed` signal
|
||||
// so an up to date global transform could be obtained when handling these.
|
||||
_notify_transform();
|
||||
|
||||
item_rect_changed(size_changed);
|
||||
if (size_changed) {
|
||||
item_rect_changed(approx_size_changed);
|
||||
if (approx_size_changed) {
|
||||
notification(NOTIFICATION_RESIZED);
|
||||
}
|
||||
}
|
||||
|
|
@ -1752,6 +1775,8 @@ void Control::_size_changed() {
|
|||
if (pos_changed && !size_changed) {
|
||||
_update_canvas_item_transform();
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
} else if (pos_changed) {
|
||||
_notify_transform();
|
||||
}
|
||||
|
|
@ -1866,6 +1891,46 @@ Control::MouseFilter Control::get_mouse_filter() const {
|
|||
return data.mouse_filter;
|
||||
}
|
||||
|
||||
Control::MouseFilter Control::get_mouse_filter_with_recursive() const {
|
||||
ERR_READ_THREAD_GUARD_V(MOUSE_FILTER_IGNORE);
|
||||
if (_is_parent_mouse_disabled()) {
|
||||
return MOUSE_FILTER_IGNORE;
|
||||
}
|
||||
return data.mouse_filter;
|
||||
}
|
||||
|
||||
void Control::set_mouse_recursive_behavior(RecursiveBehavior p_recursive_mouse_behavior) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_INDEX((int)p_recursive_mouse_behavior, 4);
|
||||
if (data.mouse_recursive_behavior == p_recursive_mouse_behavior) {
|
||||
return;
|
||||
}
|
||||
_set_mouse_recursive_behavior_ignore_cache(p_recursive_mouse_behavior);
|
||||
}
|
||||
|
||||
void Control::_set_mouse_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_mouse_behavior) {
|
||||
data.mouse_recursive_behavior = p_recursive_mouse_behavior;
|
||||
if (p_recursive_mouse_behavior == RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
Control *parent = get_parent_control();
|
||||
if (parent) {
|
||||
_propagate_mouse_behavior_recursively(parent->data.parent_mouse_recursive_behavior, false);
|
||||
} else {
|
||||
_propagate_mouse_behavior_recursively(RECURSIVE_BEHAVIOR_ENABLED, false);
|
||||
}
|
||||
} else {
|
||||
_propagate_mouse_behavior_recursively(p_recursive_mouse_behavior, false);
|
||||
}
|
||||
|
||||
if (get_viewport()) {
|
||||
get_viewport()->_gui_update_mouse_over();
|
||||
}
|
||||
}
|
||||
|
||||
Control::RecursiveBehavior Control::get_mouse_recursive_behavior() const {
|
||||
ERR_READ_THREAD_GUARD_V(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
return data.mouse_recursive_behavior;
|
||||
}
|
||||
|
||||
void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
data.force_pass_scroll_events = p_force_pass_scroll_events;
|
||||
|
|
@ -1981,7 +2046,40 @@ void Control::force_drag(const Variant &p_data, Control *p_control) {
|
|||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND(p_data.get_type() == Variant::NIL);
|
||||
|
||||
get_viewport()->_gui_force_drag(this, p_data, p_control);
|
||||
Viewport *vp = get_viewport();
|
||||
|
||||
vp->_gui_force_drag_start();
|
||||
vp->_gui_force_drag(this, p_data, p_control);
|
||||
}
|
||||
|
||||
void Control::accessibility_drag() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
|
||||
Viewport *vp = get_viewport();
|
||||
|
||||
vp->_gui_force_drag_start();
|
||||
Variant dnd_data = get_drag_data(Vector2(Math::INF, Math::INF));
|
||||
if (dnd_data.get_type() != Variant::NIL) {
|
||||
Window *w = Window::get_from_id(get_window()->get_window_id());
|
||||
if (w) {
|
||||
w->accessibility_announcement(vformat(RTR("%s grabbed. Select target and use %s to drop, use %s to cancel."), vp->gui_get_drag_description(), InputMap::get_singleton()->get_action_description("ui_accessibility_drag_and_drop"), InputMap::get_singleton()->get_action_description("ui_cancel")));
|
||||
}
|
||||
vp->_gui_force_drag(this, dnd_data, nullptr);
|
||||
queue_accessibility_update();
|
||||
} else {
|
||||
vp->_gui_force_drag_cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void Control::accessibility_drop() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND(!get_viewport()->gui_is_dragging());
|
||||
|
||||
get_viewport()->gui_perform_drop_at(Vector2(Math::INF, Math::INF), this);
|
||||
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
void Control::set_drag_preview(Control *p_control) {
|
||||
|
|
@ -2000,7 +2098,7 @@ bool Control::is_drag_successful() const {
|
|||
|
||||
void Control::set_focus_mode(FocusMode p_focus_mode) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_INDEX((int)p_focus_mode, 3);
|
||||
ERR_FAIL_INDEX((int)p_focus_mode, 4);
|
||||
|
||||
if (is_inside_tree() && p_focus_mode == FOCUS_NONE && data.focus_mode != FOCUS_NONE && has_focus()) {
|
||||
release_focus();
|
||||
|
|
@ -2014,6 +2112,42 @@ Control::FocusMode Control::get_focus_mode() const {
|
|||
return data.focus_mode;
|
||||
}
|
||||
|
||||
Control::FocusMode Control::get_focus_mode_with_recursive() const {
|
||||
ERR_READ_THREAD_GUARD_V(FOCUS_NONE);
|
||||
if (_is_focus_disabled_recursively()) {
|
||||
return FOCUS_NONE;
|
||||
}
|
||||
return data.focus_mode;
|
||||
}
|
||||
|
||||
void Control::set_focus_recursive_behavior(RecursiveBehavior p_recursive_focus_behavior) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_INDEX((int)p_recursive_focus_behavior, 4);
|
||||
if (data.focus_recursive_behavior == p_recursive_focus_behavior) {
|
||||
return;
|
||||
}
|
||||
_set_focus_recursive_behavior_ignore_cache(p_recursive_focus_behavior);
|
||||
}
|
||||
|
||||
void Control::_set_focus_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_focus_behavior) {
|
||||
data.focus_recursive_behavior = p_recursive_focus_behavior;
|
||||
if (p_recursive_focus_behavior == RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
Control *parent = get_parent_control();
|
||||
if (parent) {
|
||||
_propagate_focus_behavior_recursively(parent->data.parent_focus_recursive_behavior, false);
|
||||
} else {
|
||||
_propagate_focus_behavior_recursively(RECURSIVE_BEHAVIOR_ENABLED, false);
|
||||
}
|
||||
} else {
|
||||
_propagate_focus_behavior_recursively(p_recursive_focus_behavior, false);
|
||||
}
|
||||
}
|
||||
|
||||
Control::RecursiveBehavior Control::get_focus_recursive_behavior() const {
|
||||
ERR_READ_THREAD_GUARD_V(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
return data.focus_recursive_behavior;
|
||||
}
|
||||
|
||||
bool Control::has_focus() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return is_inside_tree() && get_viewport()->_gui_control_has_focus(this);
|
||||
|
|
@ -2054,7 +2188,7 @@ static Control *_next_control(Control *p_from) {
|
|||
return nullptr; // Can't go above.
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(p_from->get_parent());
|
||||
Control *parent = p_from->get_parent_control();
|
||||
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
|
|
@ -2077,21 +2211,25 @@ static Control *_next_control(Control *p_from) {
|
|||
|
||||
Control *Control::find_next_valid_focus() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
|
||||
// If the focus property is manually overwritten, attempt to use it.
|
||||
if (!data.focus_next.is_empty()) {
|
||||
Node *n = get_node_or_null(data.focus_next);
|
||||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Next focus node path is invalid: '" + data.focus_next + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Next focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
Control *from = const_cast<Control *>(this);
|
||||
bool ac_enabled = get_tree() && get_tree()->is_accessibility_enabled();
|
||||
|
||||
// Index of the current `Control` subtree within the containing `Window`.
|
||||
int window_next = -1;
|
||||
|
||||
while (true) {
|
||||
// If the focus property is manually overwritten, attempt to use it.
|
||||
|
||||
if (!data.focus_next.is_empty()) {
|
||||
Node *n = get_node_or_null(data.focus_next);
|
||||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Next focus node path is invalid: '" + data.focus_next + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Next focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible() && c->get_focus_mode() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// Find next child.
|
||||
|
||||
Control *next_child = nullptr;
|
||||
|
|
@ -2110,83 +2248,121 @@ Control *Control::find_next_valid_focus() const {
|
|||
next_child = _next_control(from);
|
||||
if (!next_child) { // Nothing else. Go up and find either window or subwindow.
|
||||
next_child = const_cast<Control *>(this);
|
||||
while (next_child && !next_child->is_set_as_top_level()) {
|
||||
next_child = cast_to<Control>(next_child->get_parent());
|
||||
|
||||
while (next_child) {
|
||||
if (next_child->is_set_as_top_level()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (next_child->data.RI) {
|
||||
break;
|
||||
}
|
||||
next_child = next_child->data.parent_control;
|
||||
}
|
||||
|
||||
if (!next_child) {
|
||||
next_child = const_cast<Control *>(this);
|
||||
while (next_child) {
|
||||
if (next_child->data.RI) {
|
||||
break;
|
||||
Window *win = next_child == nullptr ? nullptr : next_child->data.parent_window;
|
||||
if (win) { // Cycle through `Control` subtrees of the parent window
|
||||
if (window_next == -1) {
|
||||
window_next = next_child->get_index();
|
||||
ERR_FAIL_INDEX_V(window_next, win->get_child_count(), nullptr);
|
||||
}
|
||||
|
||||
for (int i = 1; i < win->get_child_count() + 1; i++) {
|
||||
int next = Math::wrapi(window_next + i, 0, win->get_child_count());
|
||||
Control *c = Object::cast_to<Control>(win->get_child(next));
|
||||
if (!c || !c->is_visible_in_tree() || c->is_set_as_top_level()) {
|
||||
continue;
|
||||
}
|
||||
next_child = next_child->get_parent_control();
|
||||
window_next = next;
|
||||
next_child = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (next_child == from || next_child == this) { // No next control.
|
||||
return (get_focus_mode() == FOCUS_ALL) ? next_child : nullptr;
|
||||
}
|
||||
if (next_child) {
|
||||
if (next_child->get_focus_mode() == FOCUS_ALL) {
|
||||
return next_child;
|
||||
}
|
||||
from = next_child;
|
||||
} else {
|
||||
if (!next_child) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((next_child->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && next_child->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) {
|
||||
return next_child;
|
||||
}
|
||||
|
||||
if (next_child == from || next_child == this) {
|
||||
return nullptr; // Stuck in a loop with no next control.
|
||||
}
|
||||
|
||||
from = next_child; // Try to find the next control with focus mode FOCUS_ALL.
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Control *_prev_control(Control *p_from) {
|
||||
Control *child = nullptr;
|
||||
for (int i = p_from->get_child_count() - 1; i >= 0; i--) {
|
||||
Control *c = Object::cast_to<Control>(p_from->get_child(i));
|
||||
if (!c || !c->is_visible_in_tree() || c->is_set_as_top_level()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
child = c;
|
||||
break;
|
||||
// Find the last child as prev, try the same in the last child.
|
||||
return _prev_control(c);
|
||||
}
|
||||
|
||||
if (!child) {
|
||||
return p_from;
|
||||
}
|
||||
|
||||
// No prev in parent, try the same in parent.
|
||||
return _prev_control(child);
|
||||
return p_from; // Not found in the children, return itself.
|
||||
}
|
||||
|
||||
Control *Control::find_prev_valid_focus() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
|
||||
// If the focus property is manually overwritten, attempt to use it.
|
||||
if (!data.focus_prev.is_empty()) {
|
||||
Node *n = get_node_or_null(data.focus_prev);
|
||||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Previous focus node path is invalid: '" + data.focus_prev + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Previous focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
Control *from = const_cast<Control *>(this);
|
||||
bool ac_enabled = get_tree() && get_tree()->is_accessibility_enabled();
|
||||
|
||||
// Index of the current `Control` subtree within the containing `Window`.
|
||||
int window_prev = -1;
|
||||
|
||||
while (true) {
|
||||
// If the focus property is manually overwritten, attempt to use it.
|
||||
|
||||
if (!data.focus_prev.is_empty()) {
|
||||
Node *n = get_node_or_null(data.focus_prev);
|
||||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Previous focus node path is invalid: '" + data.focus_prev + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Previous focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible() && c->get_focus_mode() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// Find prev child.
|
||||
|
||||
Control *prev_child = nullptr;
|
||||
|
||||
if (from->is_set_as_top_level() || !Object::cast_to<Control>(from->get_parent())) {
|
||||
if (from->is_set_as_top_level() || !from->data.parent_control) {
|
||||
// Find last of the children.
|
||||
|
||||
prev_child = _prev_control(from);
|
||||
Window *win = from->data.parent_window;
|
||||
if (win) { // Cycle through `Control` subtrees of the parent window
|
||||
if (window_prev == -1) {
|
||||
window_prev = from->get_index();
|
||||
ERR_FAIL_INDEX_V(window_prev, win->get_child_count(), nullptr);
|
||||
}
|
||||
|
||||
for (int i = 1; i < win->get_child_count() + 1; i++) {
|
||||
int prev = Math::wrapi(window_prev - i, 0, win->get_child_count());
|
||||
Control *c = Object::cast_to<Control>(win->get_child(prev));
|
||||
if (!c || !c->is_visible_in_tree() || c->is_set_as_top_level()) {
|
||||
continue;
|
||||
}
|
||||
window_prev = prev;
|
||||
prev_child = _prev_control(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!prev_child) {
|
||||
prev_child = _prev_control(from); // Wrap start here.
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = (from->get_index() - 1); i >= 0; i--) {
|
||||
|
|
@ -2201,21 +2377,21 @@ Control *Control::find_prev_valid_focus() const {
|
|||
}
|
||||
|
||||
if (!prev_child) {
|
||||
prev_child = Object::cast_to<Control>(from->get_parent());
|
||||
prev_child = from->data.parent_control;
|
||||
} else {
|
||||
prev_child = _prev_control(prev_child);
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_child == from || prev_child == this) { // No prev control.
|
||||
return (get_focus_mode() == FOCUS_ALL) ? prev_child : nullptr;
|
||||
}
|
||||
|
||||
if (prev_child->get_focus_mode() == FOCUS_ALL) {
|
||||
if ((prev_child->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && prev_child->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) {
|
||||
return prev_child;
|
||||
}
|
||||
|
||||
from = prev_child;
|
||||
if (prev_child == from || prev_child == this) {
|
||||
return nullptr; // Stuck in a loop with no prev control.
|
||||
}
|
||||
|
||||
from = prev_child; // Try to find the prev control with focus mode FOCUS_ALL.
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
@ -2266,14 +2442,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
|
|||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Neighbor focus node path is invalid: '" + data.focus_neighbor[p_side] + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Neighbor focus node is not a control: '" + n->get_name() + "'.");
|
||||
bool valid = true;
|
||||
if (!c->is_visible()) {
|
||||
valid = false;
|
||||
}
|
||||
if (c->get_focus_mode() == FOCUS_NONE) {
|
||||
valid = false;
|
||||
}
|
||||
if (valid) {
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -2382,6 +2551,64 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Control::_is_focus_disabled_recursively() const {
|
||||
switch (data.focus_recursive_behavior) {
|
||||
case RECURSIVE_BEHAVIOR_INHERITED:
|
||||
return data.parent_focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED;
|
||||
case RECURSIVE_BEHAVIOR_DISABLED:
|
||||
return true;
|
||||
case RECURSIVE_BEHAVIOR_ENABLED:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::_propagate_focus_behavior_recursively(RecursiveBehavior p_focus_recursive_behavior, bool p_skip_non_inherited) {
|
||||
if (is_inside_tree() && (data.focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED || (data.focus_recursive_behavior == RECURSIVE_BEHAVIOR_INHERITED && p_focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED)) && has_focus()) {
|
||||
release_focus();
|
||||
}
|
||||
|
||||
if (p_skip_non_inherited && data.focus_recursive_behavior != RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_focus_recursive_behavior = p_focus_recursive_behavior;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_focus_behavior_recursively(p_focus_recursive_behavior, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Control::_is_parent_mouse_disabled() const {
|
||||
switch (data.mouse_recursive_behavior) {
|
||||
case RECURSIVE_BEHAVIOR_INHERITED:
|
||||
return data.parent_mouse_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED;
|
||||
case RECURSIVE_BEHAVIOR_DISABLED:
|
||||
return true;
|
||||
case RECURSIVE_BEHAVIOR_ENABLED:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::_propagate_mouse_behavior_recursively(RecursiveBehavior p_mouse_recursive_behavior, bool p_skip_non_inherited) {
|
||||
if (p_skip_non_inherited && data.mouse_recursive_behavior != RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_mouse_recursive_behavior = p_mouse_recursive_behavior;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_mouse_behavior_recursively(p_mouse_recursive_behavior, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Control *Control::find_valid_focus_neighbor(Side p_side) const {
|
||||
return const_cast<Control *>(this)->_get_focus_neighbor(p_side);
|
||||
}
|
||||
|
|
@ -2391,11 +2618,13 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons
|
|||
return; // Bye.
|
||||
}
|
||||
|
||||
bool ac_enabled = get_tree() && get_tree()->is_accessibility_enabled();
|
||||
|
||||
Control *c = Object::cast_to<Control>(p_at);
|
||||
Container *container = Object::cast_to<Container>(p_at);
|
||||
bool in_container = container ? container->is_ancestor_of(this) : false;
|
||||
|
||||
if (c && c != this && c->get_focus_mode() == FOCUS_ALL && !in_container && p_clamp.intersects(c->get_global_rect())) {
|
||||
if (c && c != this && ((c->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && c->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) && !in_container && p_clamp.intersects(c->get_global_rect())) {
|
||||
Rect2 r_c = c->get_global_rect();
|
||||
r_c = r_c.intersection(p_clamp);
|
||||
real_t begin_d = p_dir.dot(r_c.get_position());
|
||||
|
|
@ -2808,6 +3037,44 @@ Variant Control::get_theme_item(Theme::DataType p_data_type, const StringName &p
|
|||
return Variant();
|
||||
}
|
||||
|
||||
Variant Control::get_used_theme_item(const String &p_full_name, const StringName &p_theme_type) const {
|
||||
if (p_full_name.begins_with("theme_override_icons/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_icons/"));
|
||||
if (has_theme_icon(name)) { // Exclude cached and default ones.
|
||||
return get_theme_icon(name);
|
||||
}
|
||||
} else if (p_full_name.begins_with("theme_override_styles/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_styles/"));
|
||||
if (has_theme_stylebox(name)) {
|
||||
return get_theme_stylebox(name);
|
||||
}
|
||||
} else if (p_full_name.begins_with("theme_override_fonts/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_fonts/"));
|
||||
if (has_theme_font(name)) {
|
||||
return get_theme_font(name);
|
||||
}
|
||||
} else if (p_full_name.begins_with("theme_override_font_sizes/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_font_sizes/"));
|
||||
if (has_theme_font_size(name)) {
|
||||
return get_theme_font_size(name);
|
||||
}
|
||||
} else if (p_full_name.begins_with("theme_override_colors/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_colors/"));
|
||||
if (has_theme_color(name)) {
|
||||
return get_theme_color(name);
|
||||
}
|
||||
} else if (p_full_name.begins_with("theme_override_constants/")) {
|
||||
String name = p_full_name.substr(strlen("theme_override_constants/"));
|
||||
if (has_theme_constant(name)) {
|
||||
return get_theme_constant(name);
|
||||
}
|
||||
} else {
|
||||
ERR_FAIL_V_MSG(Variant(), vformat("The property %s is not a theme item.", p_full_name));
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Ref<Texture2D> Control::get_editor_theme_icon(const StringName &p_name) const {
|
||||
return get_theme_icon(p_name, SNAME("EditorIcons"));
|
||||
|
|
@ -3263,6 +3530,13 @@ String Control::get_tooltip(const Point2 &p_pos) const {
|
|||
return data.tooltip;
|
||||
}
|
||||
|
||||
String Control::accessibility_get_contextual_info() const {
|
||||
ERR_READ_THREAD_GUARD_V(String());
|
||||
String ret;
|
||||
GDVIRTUAL_CALL(_accessibility_get_contextual_info, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Control *Control::make_custom_tooltip(const String &p_text) const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
Object *ret = nullptr;
|
||||
|
|
@ -3272,6 +3546,35 @@ Control *Control::make_custom_tooltip(const String &p_text) const {
|
|||
|
||||
// Base object overrides.
|
||||
|
||||
void Control::_accessibility_action_foucs(const Variant &p_data) {
|
||||
grab_focus();
|
||||
}
|
||||
|
||||
void Control::_accessibility_action_blur(const Variant &p_data) {
|
||||
release_focus();
|
||||
}
|
||||
|
||||
void Control::_accessibility_action_show_tooltip(const Variant &p_data) {
|
||||
Viewport *vp = get_viewport();
|
||||
if (vp) {
|
||||
vp->show_tooltip(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::_accessibility_action_hide_tooltip(const Variant &p_data) {
|
||||
Viewport *vp = get_viewport();
|
||||
if (vp) {
|
||||
vp->cancel_tooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void Control::_accessibility_action_scroll_into_view(const Variant &p_data) {
|
||||
ScrollContainer *sc = Object::cast_to<ScrollContainer>(get_parent());
|
||||
if (sc) {
|
||||
sc->ensure_control_visible(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::_notification(int p_notification) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
switch (p_notification) {
|
||||
|
|
@ -3283,6 +3586,31 @@ void Control::_notification(int p_notification) {
|
|||
saving = false;
|
||||
} break;
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
|
||||
RID ae = get_accessibility_element();
|
||||
ERR_FAIL_COND(ae.is_null());
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_set_transform(ae, get_transform());
|
||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(ae, Rect2(Vector2(), data.size_cache));
|
||||
DisplayServer::get_singleton()->accessibility_update_set_tooltip(ae, data.tooltip);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_CLIPS_CHILDREN, data.clip_contents);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_TOUCH_PASSTHROUGH, data.mouse_filter == MOUSE_FILTER_PASS);
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_FOCUS, callable_mp(this, &Control::_accessibility_action_foucs));
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_BLUR, callable_mp(this, &Control::_accessibility_action_blur));
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_TOOLTIP, callable_mp(this, &Control::_accessibility_action_show_tooltip));
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_HIDE_TOOLTIP, callable_mp(this, &Control::_accessibility_action_hide_tooltip));
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SCROLL_INTO_VIEW, callable_mp(this, &Control::_accessibility_action_scroll_into_view));
|
||||
if (is_inside_tree() && get_viewport()->gui_is_dragging()) {
|
||||
if (can_drop_data(Vector2(Math::INF, Math::INF), get_viewport()->gui_get_drag_data())) {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_extra_info(ae, vformat(RTR("%s can be dropped here. Use %s to drop, use %s to cancel."), get_viewport()->gui_get_drag_description(), InputMap::get_singleton()->get_action_description("ui_accessibility_drag_and_drop"), InputMap::get_singleton()->get_action_description("ui_cancel")));
|
||||
} else {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_extra_info(ae, vformat(RTR("%s can not be dropped here. Use %s to cancel."), get_viewport()->gui_get_drag_description(), InputMap::get_singleton()->get_action_description("ui_cancel")));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
data.initialized = true;
|
||||
|
||||
|
|
@ -3298,6 +3626,9 @@ void Control::_notification(int p_notification) {
|
|||
data.theme_owner->assign_theme_on_parented(this);
|
||||
|
||||
_update_layout_mode();
|
||||
|
||||
_set_focus_recursive_behavior_ignore_cache(data.focus_recursive_behavior);
|
||||
_set_mouse_recursive_behavior_ignore_cache(data.mouse_recursive_behavior);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_UNPARENTED: {
|
||||
|
|
@ -3518,6 +3849,9 @@ void Control::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode_with_recursive"), &Control::get_focus_mode_with_recursive);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_recursive_behavior", "focus_recursive_behavior"), &Control::set_focus_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_recursive_behavior"), &Control::get_focus_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("has_focus"), &Control::has_focus);
|
||||
ClassDB::bind_method(D_METHOD("grab_focus"), &Control::grab_focus);
|
||||
ClassDB::bind_method(D_METHOD("release_focus"), &Control::release_focus);
|
||||
|
|
@ -3611,8 +3945,15 @@ void Control::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("accessibility_drag"), &Control::accessibility_drag);
|
||||
ClassDB::bind_method(D_METHOD("accessibility_drop"), &Control::accessibility_drop);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_filter"), &Control::get_mouse_filter);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_filter_with_recursive"), &Control::get_mouse_filter_with_recursive);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_mouse_recursive_behavior", "mouse_recursive_behavior"), &Control::set_mouse_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_recursive_behavior"), &Control::get_mouse_recursive_behavior);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_force_pass_scroll_events", "force_pass_scroll_events"), &Control::set_force_pass_scroll_events);
|
||||
ClassDB::bind_method(D_METHOD("is_force_pass_scroll_events"), &Control::is_force_pass_scroll_events);
|
||||
|
|
@ -3708,10 +4049,12 @@ void Control::_bind_methods() {
|
|||
ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbor_bottom", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbor", "get_focus_neighbor", SIDE_BOTTOM);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_next", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_next", "get_focus_next");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_previous", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_previous", "get_focus_previous");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All,Accessibility"), "set_focus_mode", "get_focus_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_recursive_behavior", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_focus_recursive_behavior", "get_focus_recursive_behavior");
|
||||
|
||||
ADD_GROUP("Mouse", "mouse_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass (Propagate Up),Ignore"), "set_mouse_filter", "get_mouse_filter");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_recursive_behavior", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_mouse_recursive_behavior", "get_mouse_recursive_behavior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mouse_force_pass_scroll_events"), "set_force_pass_scroll_events", "is_force_pass_scroll_events");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,I-Beam,Pointing Hand,Cross,Wait,Busy,Drag,Can Drop,Forbidden,Vertical Resize,Horizontal Resize,Secondary Diagonal Resize,Main Diagonal Resize,Move,Vertical Split,Horizontal Split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
|
||||
|
||||
|
|
@ -3725,6 +4068,11 @@ void Control::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(FOCUS_NONE);
|
||||
BIND_ENUM_CONSTANT(FOCUS_CLICK);
|
||||
BIND_ENUM_CONSTANT(FOCUS_ALL);
|
||||
BIND_ENUM_CONSTANT(FOCUS_ACCESSIBILITY);
|
||||
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_DISABLED);
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_ENABLED);
|
||||
|
||||
BIND_CONSTANT(NOTIFICATION_RESIZED);
|
||||
BIND_CONSTANT(NOTIFICATION_MOUSE_ENTER);
|
||||
|
|
@ -3831,6 +4179,8 @@ void Control::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_drop_data, "at_position", "data");
|
||||
GDVIRTUAL_BIND(_make_custom_tooltip, "for_text");
|
||||
|
||||
GDVIRTUAL_BIND(_accessibility_get_contextual_info);
|
||||
|
||||
GDVIRTUAL_BIND(_gui_input, "event");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue