diff options
-rw-r--r-- | doc/classes/@GlobalScope.xml | 6 | ||||
-rw-r--r-- | doc/classes/HSplitContainer.xml | 3 | ||||
-rw-r--r-- | doc/classes/PhysicsServer2DManager.xml | 30 | ||||
-rw-r--r-- | doc/classes/PhysicsServer3DManager.xml | 30 | ||||
-rw-r--r-- | doc/classes/SplitContainer.xml | 3 | ||||
-rw-r--r-- | doc/classes/VSplitContainer.xml | 3 | ||||
-rw-r--r-- | editor/editor_themes.cpp | 3 | ||||
-rw-r--r-- | main/main.cpp | 39 | ||||
-rw-r--r-- | scene/gui/split_container.cpp | 246 | ||||
-rw-r--r-- | scene/gui/split_container.h | 30 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 3 | ||||
-rw-r--r-- | servers/physics_server_2d.cpp | 39 | ||||
-rw-r--r-- | servers/physics_server_2d.h | 42 | ||||
-rw-r--r-- | servers/physics_server_3d.cpp | 39 | ||||
-rw-r--r-- | servers/physics_server_3d.h | 42 | ||||
-rw-r--r-- | servers/register_server_types.cpp | 18 | ||||
-rw-r--r-- | tests/test_main.cpp | 4 |
17 files changed, 379 insertions, 201 deletions
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 86804e2c4c..41d1ccf2ea 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1302,9 +1302,15 @@ <member name="PhysicsServer2D" type="PhysicsServer2D" setter="" getter=""> The [PhysicsServer2D] singleton. </member> + <member name="PhysicsServer2DManager" type="PhysicsServer2DManager" setter="" getter=""> + The [PhysicsServer2DManager] singleton. + </member> <member name="PhysicsServer3D" type="PhysicsServer3D" setter="" getter=""> The [PhysicsServer3D] singleton. </member> + <member name="PhysicsServer3DManager" type="PhysicsServer3DManager" setter="" getter=""> + The [PhysicsServer3DManager] singleton. + </member> <member name="ProjectSettings" type="ProjectSettings" setter="" getter=""> The [ProjectSettings] singleton. </member> diff --git a/doc/classes/HSplitContainer.xml b/doc/classes/HSplitContainer.xml index 8137e26b8c..13915bd762 100644 --- a/doc/classes/HSplitContainer.xml +++ b/doc/classes/HSplitContainer.xml @@ -13,6 +13,9 @@ <theme_item name="autohide" data_type="constant" type="int" default="1"> Boolean value. If 1 ([code]true[/code]), the grabber will hide automatically when it isn't under the cursor. If 0 ([code]false[/code]), it's always visible. </theme_item> + <theme_item name="minimum_grab_thickness" data_type="constant" type="int" default="6"> + The minimum thickness of the area users can click on to grab the splitting line. If [theme_item separation] or [theme_item grabber]'s thickness are too small, this ensure that the splitting line can still be dragged. + </theme_item> <theme_item name="separation" data_type="constant" type="int" default="12"> The space between sides of the container. </theme_item> diff --git a/doc/classes/PhysicsServer2DManager.xml b/doc/classes/PhysicsServer2DManager.xml new file mode 100644 index 0000000000..328ac93ce3 --- /dev/null +++ b/doc/classes/PhysicsServer2DManager.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsServer2DManager" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Manager for 2D physics server implementations. + </brief_description> + <description> + [PhysicsServer2DManager] is the API for registering [PhysicsServer2D] implementations, and for setting the default implementation. + [b]Note:[/b] It is not possible to switch physics servers at runtime. This class is only used on startup at the server initialization level, by Godot itself and possibly by GDExtensions. + </description> + <tutorials> + </tutorials> + <methods> + <method name="register_server"> + <return type="void" /> + <param index="0" name="name" type="String" /> + <param index="1" name="create_callback" type="Callable" /> + <description> + Register a [PhysicsServer2D] implementation by passing a [param name] and a [Callable] that returns a [PhysicsServer2D] object. + </description> + </method> + <method name="set_default_server"> + <return type="void" /> + <param index="0" name="name" type="String" /> + <param index="1" name="priority" type="int" /> + <description> + Set the default [PhysicsServer2D] implementation to the one identified by [param name], if [param priority] is greater than the priority of the current default implementation. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/PhysicsServer3DManager.xml b/doc/classes/PhysicsServer3DManager.xml new file mode 100644 index 0000000000..3ec03fede4 --- /dev/null +++ b/doc/classes/PhysicsServer3DManager.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsServer3DManager" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Manager for 3D physics server implementations. + </brief_description> + <description> + [PhysicsServer3DManager] is the API for registering [PhysicsServer3D] implementations, and for setting the default implementation. + [b]Note:[/b] It is not possible to switch physics servers at runtime. This class is only used on startup at the server initialization level, by Godot itself and possibly by GDExtensions. + </description> + <tutorials> + </tutorials> + <methods> + <method name="register_server"> + <return type="void" /> + <param index="0" name="name" type="String" /> + <param index="1" name="create_callback" type="Callable" /> + <description> + Register a [PhysicsServer3D] implementation by passing a [param name] and a [Callable] that returns a [PhysicsServer2D] object. + </description> + </method> + <method name="set_default_server"> + <return type="void" /> + <param index="0" name="name" type="String" /> + <param index="1" name="priority" type="int" /> + <description> + Set the default [PhysicsServer3D] implementation to the one identified by [param name], if [param priority] is greater than the priority of the current default implementation. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml index f5646e9e97..f0998deeae 100644 --- a/doc/classes/SplitContainer.xml +++ b/doc/classes/SplitContainer.xml @@ -55,6 +55,9 @@ <theme_item name="autohide" data_type="constant" type="int" default="1"> Boolean value. If 1 ([code]true[/code]), the grabber will hide automatically when it isn't under the cursor. If 0 ([code]false[/code]), it's always visible. </theme_item> + <theme_item name="minimum_grab_thickness" data_type="constant" type="int" default="6"> + The minimum thickness of the area users can click on to grab the splitting line. If [theme_item separation] or [theme_item h_grabber] / [theme_item v_grabber]'s thickness are too small, this ensure that the splitting line can still be dragged. + </theme_item> <theme_item name="separation" data_type="constant" type="int" default="12"> The space between sides of the container. </theme_item> diff --git a/doc/classes/VSplitContainer.xml b/doc/classes/VSplitContainer.xml index b933fb2805..c60d15d9c9 100644 --- a/doc/classes/VSplitContainer.xml +++ b/doc/classes/VSplitContainer.xml @@ -13,6 +13,9 @@ <theme_item name="autohide" data_type="constant" type="int" default="1"> Boolean value. If 1 ([code]true[/code]), the grabber will hide automatically when it isn't under the cursor. If 0 ([code]false[/code]), it's always visible. </theme_item> + <theme_item name="minimum_grab_thickness" data_type="constant" type="int" default="6"> + The minimum thickness of the area users can click on to grab the splitting line. If [theme_item separation] or [theme_item grabber]'s thickness are too small, this ensure that the splitting line can still be dragged. + </theme_item> <theme_item name="separation" data_type="constant" type="int" default="12"> The space between sides of the container. </theme_item> diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 67e5fc95b9..9e983839f9 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1328,6 +1328,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); + theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE); + theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE); + // Containers theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); diff --git a/main/main.cpp b/main/main.cpp index 650d1159e0..0ce3ef20be 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -126,7 +126,9 @@ static RenderingServer *rendering_server = nullptr; static CameraServer *camera_server = nullptr; static XRServer *xr_server = nullptr; static TextServerManager *tsman = nullptr; +static PhysicsServer3DManager *physics_server_3d_manager = nullptr; static PhysicsServer3D *physics_server_3d = nullptr; +static PhysicsServer2DManager *physics_server_2d_manager = nullptr; static PhysicsServer2D *physics_server_2d = nullptr; static NavigationServer3D *navigation_server_3d = nullptr; static NavigationServer2D *navigation_server_2d = nullptr; @@ -223,25 +225,24 @@ static String get_full_version_string() { return String(VERSION_FULL_BUILD) + hash; } -// FIXME: Could maybe be moved to PhysicsServer3DManager and PhysicsServer2DManager directly -// to have less code in main.cpp. +// FIXME: Could maybe be moved to have less code in main.cpp. void initialize_physics() { /// 3D Physics Server - physics_server_3d = PhysicsServer3DManager::new_server( + physics_server_3d = PhysicsServer3DManager::get_singleton()->new_server( ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name)); if (!physics_server_3d) { // Physics server not found, Use the default physics - physics_server_3d = PhysicsServer3DManager::new_default_server(); + physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server(); } ERR_FAIL_COND(!physics_server_3d); physics_server_3d->init(); - /// 2D Physics server - physics_server_2d = PhysicsServer2DManager::new_server( - ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name)); + // 2D Physics server + physics_server_2d = PhysicsServer2DManager::get_singleton()->new_server( + ProjectSettings::get_singleton()->get(PhysicsServer2DManager::get_singleton()->setting_property_name)); if (!physics_server_2d) { // Physics server not found, Use the default physics - physics_server_2d = PhysicsServer2DManager::new_default_server(); + physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server(); } ERR_FAIL_COND(!physics_server_2d); physics_server_2d->init(); @@ -450,6 +451,9 @@ Error Main::test_setup() { tsman->add_interface(ts); } + physics_server_3d_manager = memnew(PhysicsServer3DManager); + physics_server_2d_manager = memnew(PhysicsServer2DManager); + // From `Main::setup2()`. initialize_modules(MODULE_INITIALIZATION_LEVEL_CORE); register_core_extensions(); @@ -555,6 +559,12 @@ void Main::test_cleanup() { if (tsman) { memdelete(tsman); } + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } if (globals) { memdelete(globals); } @@ -1783,6 +1793,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) { tsman->add_interface(ts); } + physics_server_3d_manager = memnew(PhysicsServer3DManager); + physics_server_2d_manager = memnew(PhysicsServer2DManager); + register_server_types(); initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); @@ -3156,6 +3169,9 @@ void Main::cleanup(bool p_force) { finalize_theme_db(); + // Before deinitializing server extensions, finalize servers which may be loaded as extensions. + finalize_physics(); + NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); unregister_server_types(); @@ -3177,7 +3193,6 @@ void Main::cleanup(bool p_force) { OS::get_singleton()->finalize(); - finalize_physics(); finalize_navigation_server(); finalize_display(); @@ -3206,6 +3221,12 @@ void Main::cleanup(bool p_force) { if (tsman) { memdelete(tsman); } + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } if (globals) { memdelete(globals); } diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d721ebe015..2ca1d6239e 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -33,11 +33,99 @@ #include "label.h" #include "margin_container.h" +void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); + + if (sc->collapsed || !sc->_getch(0) || !sc->_getch(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) { + return; + } + + Ref<InputEventMouseButton> mb = p_event; + + if (mb.is_valid()) { + if (mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + sc->_compute_middle_sep(true); + dragging = true; + drag_ofs = sc->split_offset; + if (sc->vertical) { + drag_from = get_transform().xform(mb->get_position()).y; + } else { + drag_from = get_transform().xform(mb->get_position()).x; + } + } else { + dragging = false; + queue_redraw(); + } + } + } + + Ref<InputEventMouseMotion> mm = p_event; + + if (mm.is_valid()) { + if (!dragging) { + return; + } + + Vector2i in_parent_pos = get_transform().xform(mm->get_position()); + if (!sc->vertical && is_layout_rtl()) { + sc->split_offset = drag_ofs - ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from); + } else { + sc->split_offset = drag_ofs + ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from); + } + sc->_compute_middle_sep(true); + sc->queue_sort(); + sc->emit_signal(SNAME("dragged"), sc->get_split_offset()); + } +} + +Control::CursorShape SplitContainerDragger::get_cursor_shape(const Point2 &p_pos) const { + SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); + + if (!sc->collapsed && sc->dragger_visibility == SplitContainer::DRAGGER_VISIBLE) { + return (sc->vertical ? CURSOR_VSPLIT : CURSOR_HSPLIT); + } + + return Control::get_cursor_shape(p_pos); +} + +void SplitContainerDragger::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_MOUSE_ENTER: { + mouse_inside = true; + SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); + if (sc->get_theme_constant(SNAME("autohide"))) { + queue_redraw(); + } + } break; + + case NOTIFICATION_MOUSE_EXIT: { + mouse_inside = false; + SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); + if (sc->get_theme_constant(SNAME("autohide"))) { + queue_redraw(); + } + } break; + + case NOTIFICATION_DRAW: { + SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); + if (!dragging && !mouse_inside && sc->get_theme_constant(SNAME("autohide"))) { + return; + } + + Ref<Texture2D> tex = sc->get_theme_icon(SNAME("grabber")); + draw_texture(tex, (get_size() - tex->get_size()) / 2); + } break; + } +} + Control *SplitContainer::_getch(int p_idx) const { int idx = 0; - for (int i = 0; i < get_child_count(); i++) { - Control *c = Object::cast_to<Control>(get_child(i)); + for (int i = 0; i < get_child_count(false); i++) { + Control *c = Object::cast_to<Control>(get_child(i, false)); if (!c || !c->is_visible()) { continue; } @@ -114,22 +202,25 @@ void SplitContainer::_resort() { Control *first = _getch(0); Control *second = _getch(1); - // If we have only one element + // If we have only one element. if (!first || !second) { if (first) { fit_child_in_rect(first, Rect2(Point2(), get_size())); } else if (second) { fit_child_in_rect(second, Rect2(Point2(), get_size())); } + dragging_area_control->hide(); return; } // If we have more that one. _compute_middle_sep(false); + // Determine the separation between items. Ref<Texture2D> g = _get_grabber_icon(); int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0; + // Move the children, including the dragger. if (vertical) { fit_child_in_rect(first, Rect2(Point2(0, 0), Size2(get_size().width, middle_sep))); int sofs = middle_sep + sep; @@ -147,7 +238,21 @@ void SplitContainer::_resort() { } } - queue_redraw(); + // Handle the dragger visibility and position. + if (dragger_visibility == DRAGGER_VISIBLE && !collapsed) { + dragging_area_control->show(); + + int dragger_ctrl_size = MAX(sep, theme_cache.minimum_grab_thickness); + if (vertical) { + dragging_area_control->set_rect(Rect2(Point2(0, middle_sep - (dragger_ctrl_size - sep) / 2), Size2(get_size().width, dragger_ctrl_size))); + } else { + dragging_area_control->set_rect(Rect2(Point2(middle_sep - (dragger_ctrl_size - sep) / 2, 0), Size2(dragger_ctrl_size, get_size().height))); + } + + dragging_area_control->queue_redraw(); + } else { + dragging_area_control->hide(); + } } Size2 SplitContainer::get_minimum_size() const { @@ -182,10 +287,17 @@ Size2 SplitContainer::get_minimum_size() const { return minimum; } +void SplitContainer::_validate_property(PropertyInfo &p_property) const { + if (is_fixed && p_property.name == "vertical") { + p_property.usage = PROPERTY_USAGE_NONE; + } +} + void SplitContainer::_update_theme_item_cache() { Container::_update_theme_item_cache(); theme_cache.separation = get_theme_constant(SNAME("separation")); + theme_cache.minimum_grab_thickness = get_theme_constant(SNAME("minimum_grab_thickness")); theme_cache.autohide = get_theme_constant(SNAME("autohide")); theme_cache.grabber_icon = get_theme_icon(SNAME("grabber")); theme_cache.grabber_icon_h = get_theme_icon(SNAME("h_grabber")); @@ -203,134 +315,12 @@ void SplitContainer::_notification(int p_what) { _resort(); } break; - case NOTIFICATION_MOUSE_EXIT: { - mouse_inside = false; - if (theme_cache.autohide) { - queue_redraw(); - } - } break; - - case NOTIFICATION_DRAW: { - if (!_getch(0) || !_getch(1)) { - return; - } - - if (collapsed || (!dragging && !mouse_inside && theme_cache.autohide)) { - return; - } - - if (dragger_visibility != DRAGGER_VISIBLE) { - return; - } - - int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? theme_cache.separation : 0; - Ref<Texture2D> tex = theme_cache.grabber_icon; - Size2 size = get_size(); - - if (vertical) { - draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2)); - } else { - draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); - } - } break; - case NOTIFICATION_THEME_CHANGED: { update_minimum_size(); } break; } } -void SplitContainer::_validate_property(PropertyInfo &p_property) const { - if (is_fixed && p_property.name == "vertical") { - p_property.usage = PROPERTY_USAGE_NONE; - } -} - -void SplitContainer::gui_input(const Ref<InputEvent> &p_event) { - ERR_FAIL_COND(p_event.is_null()); - - if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility != DRAGGER_VISIBLE) { - return; - } - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - if (mb->get_button_index() == MouseButton::LEFT) { - if (mb->is_pressed()) { - if (vertical) { - if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + theme_cache.separation) { - _compute_middle_sep(true); - dragging = true; - drag_from = mb->get_position().y; - drag_ofs = split_offset; - } - } else { - if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + theme_cache.separation) { - _compute_middle_sep(true); - dragging = true; - drag_from = mb->get_position().x; - drag_ofs = split_offset; - } - } - } else { - dragging = false; - } - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - bool mouse_inside_state = false; - if (vertical) { - mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + theme_cache.separation; - } else { - mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + theme_cache.separation; - } - - if (mouse_inside != mouse_inside_state) { - mouse_inside = mouse_inside_state; - if (theme_cache.autohide) { - queue_redraw(); - } - } - - if (!dragging) { - return; - } - - if (!vertical && is_layout_rtl()) { - split_offset = drag_ofs - ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); - } else { - split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); - } - _compute_middle_sep(true); - queue_sort(); - emit_signal(SNAME("dragged"), get_split_offset()); - } -} - -Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const { - if (dragging) { - return (vertical ? CURSOR_VSPLIT : CURSOR_HSPLIT); - } - - if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) { - if (vertical) { - if (p_pos.y > middle_sep && p_pos.y < middle_sep + theme_cache.separation) { - return CURSOR_VSPLIT; - } - } else { - if (p_pos.x > middle_sep && p_pos.x < middle_sep + theme_cache.separation) { - return CURSOR_HSPLIT; - } - } - } - - return Control::get_cursor_shape(p_pos); -} - void SplitContainer::set_split_offset(int p_offset) { if (split_offset == p_offset) { return; @@ -370,7 +360,6 @@ void SplitContainer::set_dragger_visibility(DraggerVisibility p_visibility) { dragger_visibility = p_visibility; queue_sort(); - queue_redraw(); } SplitContainer::DraggerVisibility SplitContainer::get_dragger_visibility() const { @@ -444,4 +433,7 @@ void SplitContainer::_bind_methods() { SplitContainer::SplitContainer(bool p_vertical) { vertical = p_vertical; + + dragging_area_control = memnew(SplitContainerDragger); + add_child(dragging_area_control, false, Node::INTERNAL_MODE_BACK); } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 598b0ba485..d297e3a3ea 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -33,8 +33,26 @@ #include "scene/gui/container.h" +class SplitContainerDragger : public Control { + GDCLASS(SplitContainerDragger, Control); + +protected: + void _notification(int p_what); + virtual void gui_input(const Ref<InputEvent> &p_event) override; + +private: + bool dragging = false; + int drag_from = 0; + int drag_ofs = 0; + bool mouse_inside = false; + +public: + virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; +}; + class SplitContainer : public Container { GDCLASS(SplitContainer, Container); + friend class SplitContainerDragger; public: enum DraggerVisibility { @@ -47,15 +65,14 @@ private: int split_offset = 0; int middle_sep = 0; bool vertical = false; - bool dragging = false; - int drag_from = 0; - int drag_ofs = 0; bool collapsed = false; DraggerVisibility dragger_visibility = DRAGGER_VISIBLE; - bool mouse_inside = false; + + SplitContainerDragger *dragging_area_control = nullptr; struct ThemeCache { int separation = 0; + int minimum_grab_thickness = 0; int autohide = 0; Ref<Texture2D> grabber_icon; Ref<Texture2D> grabber_icon_h; @@ -68,10 +85,11 @@ private: void _compute_middle_sep(bool p_clamp); void _resort(); + void _dragging_area_gui_input(const Ref<InputEvent> &p_event); + protected: bool is_fixed = false; - virtual void gui_input(const Ref<InputEvent> &p_event) override; virtual void _update_theme_item_cache() override; void _notification(int p_what); @@ -92,8 +110,6 @@ public: void set_vertical(bool p_vertical); bool is_vertical() const; - virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; - virtual Size2 get_minimum_size() const override; virtual Vector<int> get_allowed_size_flags_horizontal() const override; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index fd9ebdab01..869d582935 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -988,6 +988,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("separation", "SplitContainer", 12 * scale); theme->set_constant("separation", "HSplitContainer", 12 * scale); theme->set_constant("separation", "VSplitContainer", 12 * scale); + theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * scale); + theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * scale); + theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * scale); theme->set_constant("autohide", "SplitContainer", 1 * scale); theme->set_constant("autohide", "HSplitContainer", 1 * scale); theme->set_constant("autohide", "VSplitContainer", 1 * scale); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 528ac18f88..abaa473017 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -876,9 +876,7 @@ PhysicsServer2D::~PhysicsServer2D() { singleton = nullptr; } -Vector<PhysicsServer2DManager::ClassInfo> PhysicsServer2DManager::physics_2d_servers; -int PhysicsServer2DManager::default_server_id = -1; -int PhysicsServer2DManager::default_server_priority = -1; +PhysicsServer2DManager *PhysicsServer2DManager::singleton = nullptr; const String PhysicsServer2DManager::setting_property_name(PNAME("physics/2d/physics_engine")); void PhysicsServer2DManager::on_servers_changed() { @@ -889,10 +887,19 @@ void PhysicsServer2DManager::on_servers_changed() { ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers)); } -void PhysicsServer2DManager::register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback) { - ERR_FAIL_COND(!p_creat_callback); +void PhysicsServer2DManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer2DManager::register_server); + ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer2DManager::set_default_server); +} + +PhysicsServer2DManager *PhysicsServer2DManager::get_singleton() { + return singleton; +} + +void PhysicsServer2DManager::register_server(const String &p_name, const Callable &p_create_callback) { + //ERR_FAIL_COND(!p_create_callback.is_valid()); ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback)); + physics_2d_servers.push_back(ClassInfo(p_name, p_create_callback)); on_servers_changed(); } @@ -925,7 +932,11 @@ String PhysicsServer2DManager::get_server_name(int p_id) { PhysicsServer2D *PhysicsServer2DManager::new_default_server() { ERR_FAIL_COND_V(default_server_id == -1, nullptr); - return physics_2d_servers[default_server_id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_2d_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer2D>(ret.get_validated_object()); } PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) { @@ -933,6 +944,18 @@ PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) { if (id == -1) { return nullptr; } else { - return physics_2d_servers[id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_2d_servers[id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer2D>(ret.get_validated_object()); } } + +PhysicsServer2DManager::PhysicsServer2DManager() { + singleton = this; +} + +PhysicsServer2DManager::~PhysicsServer2DManager() { + singleton = nullptr; +} diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index f1e05e7a46..d5b4dc05e6 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -766,16 +766,18 @@ public: real_t get_collision_unsafe_fraction() const; }; -typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)(); +class PhysicsServer2DManager : public Object { + GDCLASS(PhysicsServer2DManager, Object); + + static PhysicsServer2DManager *singleton; -class PhysicsServer2DManager { struct ClassInfo { String name; - CreatePhysicsServer2DCallback create_callback = nullptr; + Callable create_callback; ClassInfo() {} - ClassInfo(String p_name, CreatePhysicsServer2DCallback p_create_callback) : + ClassInfo(String p_name, Callable p_create_callback) : name(p_name), create_callback(p_create_callback) {} @@ -789,24 +791,30 @@ class PhysicsServer2DManager { } }; - static Vector<ClassInfo> physics_2d_servers; - static int default_server_id; - static int default_server_priority; + Vector<ClassInfo> physics_2d_servers; + int default_server_id = -1; + int default_server_priority = -1; + + void on_servers_changed(); + +protected: + static void _bind_methods(); public: static const String setting_property_name; -private: - static void on_servers_changed(); + static PhysicsServer2DManager *get_singleton(); -public: - static void register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static PhysicsServer2D *new_default_server(); - static PhysicsServer2D *new_server(const String &p_name); + void register_server(const String &p_name, const Callable &p_create_callback); + void set_default_server(const String &p_name, int p_priority = 0); + int find_server_id(const String &p_name); + int get_servers_count(); + String get_server_name(int p_id); + PhysicsServer2D *new_default_server(); + PhysicsServer2D *new_server(const String &p_name); + + PhysicsServer2DManager(); + ~PhysicsServer2DManager(); }; VARIANT_ENUM_CAST(PhysicsServer2D::ShapeType); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index fc32e1f665..b4f30d7649 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -1046,9 +1046,7 @@ PhysicsServer3D::~PhysicsServer3D() { singleton = nullptr; } -Vector<PhysicsServer3DManager::ClassInfo> PhysicsServer3DManager::physics_servers; -int PhysicsServer3DManager::default_server_id = -1; -int PhysicsServer3DManager::default_server_priority = -1; +PhysicsServer3DManager *PhysicsServer3DManager::singleton = nullptr; const String PhysicsServer3DManager::setting_property_name(PNAME("physics/3d/physics_engine")); void PhysicsServer3DManager::on_servers_changed() { @@ -1059,10 +1057,19 @@ void PhysicsServer3DManager::on_servers_changed() { ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2)); } -void PhysicsServer3DManager::register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback) { - ERR_FAIL_COND(!p_creat_callback); +void PhysicsServer3DManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer3DManager::register_server); + ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer3DManager::set_default_server); +} + +PhysicsServer3DManager *PhysicsServer3DManager::get_singleton() { + return singleton; +} + +void PhysicsServer3DManager::register_server(const String &p_name, const Callable &p_create_callback) { + //ERR_FAIL_COND(!p_create_callback.is_valid()); ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_servers.push_back(ClassInfo(p_name, p_creat_callback)); + physics_servers.push_back(ClassInfo(p_name, p_create_callback)); on_servers_changed(); } @@ -1095,7 +1102,11 @@ String PhysicsServer3DManager::get_server_name(int p_id) { PhysicsServer3D *PhysicsServer3DManager::new_default_server() { ERR_FAIL_COND_V(default_server_id == -1, nullptr); - return physics_servers[default_server_id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer3D>(ret.get_validated_object()); } PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) { @@ -1103,6 +1114,18 @@ PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) { if (id == -1) { return nullptr; } else { - return physics_servers[id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_servers[id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer3D>(ret.get_validated_object()); } } + +PhysicsServer3DManager::PhysicsServer3DManager() { + singleton = this; +} + +PhysicsServer3DManager::~PhysicsServer3DManager() { + singleton = nullptr; +} diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 6237ed67aa..1308e4cd36 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -983,16 +983,18 @@ public: real_t get_collision_depth(int p_collision_index = 0) const; }; -typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)(); +class PhysicsServer3DManager : public Object { + GDCLASS(PhysicsServer3DManager, Object); + + static PhysicsServer3DManager *singleton; -class PhysicsServer3DManager { struct ClassInfo { String name; - CreatePhysicsServer3DCallback create_callback = nullptr; + Callable create_callback; ClassInfo() {} - ClassInfo(String p_name, CreatePhysicsServer3DCallback p_create_callback) : + ClassInfo(String p_name, Callable p_create_callback) : name(p_name), create_callback(p_create_callback) {} @@ -1006,24 +1008,30 @@ class PhysicsServer3DManager { } }; - static Vector<ClassInfo> physics_servers; - static int default_server_id; - static int default_server_priority; + Vector<ClassInfo> physics_servers; + int default_server_id = -1; + int default_server_priority = -1; + + void on_servers_changed(); + +protected: + static void _bind_methods(); public: static const String setting_property_name; -private: - static void on_servers_changed(); + static PhysicsServer3DManager *get_singleton(); -public: - static void register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static PhysicsServer3D *new_default_server(); - static PhysicsServer3D *new_server(const String &p_name); + void register_server(const String &p_name, const Callable &p_create_callback); + void set_default_server(const String &p_name, int p_priority = 0); + int find_server_id(const String &p_name); + int get_servers_count(); + String get_server_name(int p_id); + PhysicsServer3D *new_default_server(); + PhysicsServer3D *new_server(const String &p_name); + + PhysicsServer3DManager(); + ~PhysicsServer3DManager(); }; VARIANT_ENUM_CAST(PhysicsServer3D::ShapeType); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 2e794683b9..b9667f338c 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -85,7 +85,7 @@ ShaderTypes *shader_types = nullptr; -PhysicsServer3D *_createGodotPhysics3DCallback() { +static PhysicsServer3D *_createGodotPhysics3DCallback() { bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread"); PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads)); @@ -93,7 +93,7 @@ PhysicsServer3D *_createGodotPhysics3DCallback() { return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads)); } -PhysicsServer2D *_createGodotPhysics2DCallback() { +static PhysicsServer2D *_createGodotPhysics2DCallback() { bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread"); PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads)); @@ -133,6 +133,9 @@ void register_server_types() { GDREGISTER_ABSTRACT_CLASS(RenderingServer); GDREGISTER_CLASS(AudioServer); + GDREGISTER_CLASS(PhysicsServer2DManager); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2DManager", PhysicsServer2DManager::get_singleton(), "PhysicsServer2DManager")); + GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D); GDREGISTER_VIRTUAL_CLASS(PhysicsServer2DExtension); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2DExtension); @@ -144,6 +147,9 @@ void register_server_types() { GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape"); GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState2D *p_state)"); + GDREGISTER_CLASS(PhysicsServer3DManager); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager")); + GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D); GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension); @@ -264,15 +270,15 @@ void register_server_types() { GLOBAL_DEF(PhysicsServer2DManager::setting_property_name, "DEFAULT"); ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer2DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServer2DManager::register_server("GodotPhysics2D", &_createGodotPhysics2DCallback); - PhysicsServer2DManager::set_default_server("GodotPhysics2D"); + PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback)); + PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D"); // Physics 3D GLOBAL_DEF(PhysicsServer3DManager::setting_property_name, "DEFAULT"); ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer3DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback); - PhysicsServer3DManager::set_default_server("GodotPhysics3D"); + PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback)); + PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D"); writer_mjpeg = memnew(MovieWriterMJPEG); MovieWriter::add_writer(writer_mjpeg); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 7712189e45..4c861eacba 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -207,10 +207,10 @@ struct GodotTestCaseListener : public doctest::IReporter { RenderingServerDefault::get_singleton()->init(); RenderingServerDefault::get_singleton()->set_render_loop_enabled(false); - physics_server_3d = PhysicsServer3DManager::new_default_server(); + physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server(); physics_server_3d->init(); - physics_server_2d = PhysicsServer2DManager::new_default_server(); + physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server(); physics_server_2d->init(); navigation_server_3d = NavigationServer3DManager::new_default_server(); |