mirror of
https://github.com/godotengine/godot.git
synced 2024-11-12 23:24:26 +00:00
Add ios virtual controller support.
This commit is contained in:
parent
1bffd6c73b
commit
7903c5fe85
@ -1576,6 +1576,13 @@ ProjectSettings::ProjectSettings() {
|
||||
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false);
|
||||
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_controller", false);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_left_thumbstick", true);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_right_thumbstick", true);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_button_a", true);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_button_b", true);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_button_x", true);
|
||||
GLOBAL_DEF_BASIC("input_devices/virtual_controller/ios/enable_button_y", true);
|
||||
|
||||
// These properties will not show up in the dialog. If you want to exclude whole groups, use add_hidden_prefix().
|
||||
GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray());
|
||||
|
@ -188,6 +188,7 @@ void Input::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("is_emulating_mouse_from_touch"), &Input::is_emulating_mouse_from_touch);
|
||||
ClassDB::bind_method(D_METHOD("set_emulate_touch_from_mouse", "enable"), &Input::set_emulate_touch_from_mouse);
|
||||
ClassDB::bind_method(D_METHOD("is_emulating_touch_from_mouse"), &Input::is_emulating_touch_from_mouse);
|
||||
ClassDB::bind_method(D_METHOD("get_virtual_controller"), &Input::get_virtual_controller);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_mode"), "set_mouse_mode", "get_mouse_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_accumulated_input"), "set_use_accumulated_input", "is_using_accumulated_input");
|
||||
@ -1054,6 +1055,10 @@ bool Input::is_emulating_touch_from_mouse() const {
|
||||
return emulate_touch_from_mouse;
|
||||
}
|
||||
|
||||
VirtualController *Input::get_virtual_controller() {
|
||||
return OS::get_singleton()->get_virtual_controller();
|
||||
}
|
||||
|
||||
// Calling this whenever the game window is focused helps unsticking the "touch mouse"
|
||||
// if the OS or its abstraction class hasn't properly reported that touch pointers raised
|
||||
void Input::ensure_touch_mouse_raised() {
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define INPUT_H
|
||||
|
||||
#include "core/input/input_event.h"
|
||||
#include "core/input/virtual_controller.h"
|
||||
#include "core/object/object.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/os/thread_safe.h"
|
||||
@ -383,6 +384,8 @@ public:
|
||||
void set_use_accumulated_input(bool p_enable);
|
||||
bool is_using_accumulated_input();
|
||||
|
||||
VirtualController *get_virtual_controller();
|
||||
|
||||
void release_pressed_events();
|
||||
|
||||
void set_event_dispatch_function(EventDispatchFunc p_function);
|
||||
|
49
core/input/virtual_controller.cpp
Normal file
49
core/input/virtual_controller.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/**************************************************************************/
|
||||
/* virtual_controller.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "virtual_controller.h"
|
||||
|
||||
void VirtualController::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("enable"), &VirtualController::enable);
|
||||
ClassDB::bind_method(D_METHOD("disable"), &VirtualController::disable);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled"), &VirtualController::is_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_left_thumbstick", "enable"), &VirtualController::set_enabled_left_thumbstick);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_left_thumbstick"), &VirtualController::is_enabled_left_thumbstick);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_right_thumbstick", "enable"), &VirtualController::set_enabled_right_thumbstick);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_right_thumbstick"), &VirtualController::is_enabled_right_thumbstick);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_button_a", "enable"), &VirtualController::set_enabled_button_a);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_button_a"), &VirtualController::is_enabled_button_a);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_button_b", "enable"), &VirtualController::set_enabled_button_b);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_button_b"), &VirtualController::is_enabled_button_b);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_button_x", "enable"), &VirtualController::set_enabled_button_x);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_button_x"), &VirtualController::is_enabled_button_x);
|
||||
ClassDB::bind_method(D_METHOD("set_enabled_button_y", "enable"), &VirtualController::set_enabled_button_y);
|
||||
ClassDB::bind_method(D_METHOD("is_enabled_button_y"), &VirtualController::is_enabled_button_y);
|
||||
}
|
60
core/input/virtual_controller.h
Normal file
60
core/input/virtual_controller.h
Normal file
@ -0,0 +1,60 @@
|
||||
/**************************************************************************/
|
||||
/* virtual_controller.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef VIRTUAL_CONTROLLER_H
|
||||
#define VIRTUAL_CONTROLLER_H
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
|
||||
class VirtualController : public Object {
|
||||
GDCLASS(VirtualController, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void enable() = 0;
|
||||
virtual void disable() = 0;
|
||||
virtual bool is_enabled() = 0;
|
||||
virtual void set_enabled_left_thumbstick(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_left_thumbstick() = 0;
|
||||
virtual void set_enabled_right_thumbstick(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_right_thumbstick() = 0;
|
||||
virtual void set_enabled_button_a(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_button_a() = 0;
|
||||
virtual void set_enabled_button_b(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_button_b() = 0;
|
||||
virtual void set_enabled_button_x(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_button_x() = 0;
|
||||
virtual void set_enabled_button_y(bool p_enabled) = 0;
|
||||
virtual bool is_enabled_button_y() = 0;
|
||||
};
|
||||
|
||||
#endif // VIRTUAL_CONTROLLER_H
|
@ -700,6 +700,10 @@ void OS::benchmark_dump() {
|
||||
#endif
|
||||
}
|
||||
|
||||
VirtualController *OS::get_virtual_controller() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OS::OS() {
|
||||
singleton = this;
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define OS_H
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/input/virtual_controller.h"
|
||||
#include "core/io/logger.h"
|
||||
#include "core/io/remote_filesystem_client.h"
|
||||
#include "core/os/time_enums.h"
|
||||
@ -344,6 +345,8 @@ public:
|
||||
// This is invoked by the GDExtensionManager after loading GDExtensions specified by the project.
|
||||
virtual void load_platform_gdextensions() const {}
|
||||
|
||||
virtual VirtualController *get_virtual_controller() const;
|
||||
|
||||
OS();
|
||||
virtual ~OS();
|
||||
};
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "core/input/input.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/input/shortcut.h"
|
||||
#include "core/input/virtual_controller.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/dtls_server.h"
|
||||
@ -298,6 +299,8 @@ void register_core_types() {
|
||||
GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right");
|
||||
GDREGISTER_NATIVE_STRUCT(ScriptLanguageExtensionProfilingInfo, "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time");
|
||||
|
||||
GDREGISTER_ABSTRACT_CLASS(VirtualController);
|
||||
|
||||
worker_thread_pool = memnew(WorkerThreadPool);
|
||||
|
||||
OS::get_singleton()->benchmark_end_measure("Core", "Register Types");
|
||||
|
@ -195,6 +195,13 @@
|
||||
By default, the deadzone is automatically calculated from the average of the action deadzones. However, you can override the deadzone to be whatever you want (on the range of 0 to 1).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_virtual_controller">
|
||||
<return type="VirtualController" />
|
||||
<description>
|
||||
Return platform-specific virtual controller or null. (See [VirtualController])
|
||||
[b]Note:[/b] Currently implemented only on iOS 15.0+.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_action_just_pressed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="action" type="StringName" />
|
||||
|
@ -1456,6 +1456,28 @@
|
||||
<member name="input_devices/sensors/enable_magnetometer" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], the magnetometer sensor is enabled and [method Input.get_magnetometer] returns valid data.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_button_a" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the button "A" shows in the virtual controller.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_button_b" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the button "B" shows in the virtual controller.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_button_x" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the button "X" shows in the virtual controller.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_button_y" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the button "Y" shows in the virtual controller.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_controller" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], if there are no physical controllers connected, the game shows the virtual controller.
|
||||
[b]Note:[/b] Currently implemented only on iOS 15.0+.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_left_thumbstick" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the left thumbstick shows in the virtual controller.
|
||||
</member>
|
||||
<member name="input_devices/virtual_controller/ios/enable_right_thumbstick" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], the right thumbstick shows in the virtual controller.
|
||||
</member>
|
||||
<member name="internationalization/locale/fallback" type="String" setter="" getter="" default=""en"">
|
||||
The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used.
|
||||
</member>
|
||||
|
112
doc/classes/VirtualController.xml
Normal file
112
doc/classes/VirtualController.xml
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VirtualController" inherits="Object" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
A software emulation of a real controller that you configure specifically for your game.
|
||||
</brief_description>
|
||||
<description>
|
||||
Use a virtual controller to display software controls that you can customize over your game.
|
||||
You create a virtual controller from a configuration where you choose the input elements to display.
|
||||
When you connect the controller to the device, users interact with it similarly to a real controller.
|
||||
[b]Note:[/b] Currently implemented only on iOS 15.0+.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="disable">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Disconnects the virtual controller from the device and removes it from the screen.
|
||||
</description>
|
||||
</method>
|
||||
<method name="enable">
|
||||
<return type="void" />
|
||||
<description>
|
||||
If there are no physical controllers connected, connects the virtual controller to the device and displays it on the screen.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the virtual controller is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_button_a">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the button "A" is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_button_b">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the button "B" is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_button_x">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the button "X" is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_button_y">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the button "Y" is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_left_thumbstick">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the left thumbstick is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_enabled_right_thumbstick">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the right thumbstick is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_button_a">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a button "A" element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_button_b">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a button "B" element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_button_x">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a button "A" element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_button_y">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a button "Y" element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_left_thumbstick">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a left thumbstick element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabled_right_thumbstick">
|
||||
<return type="void" />
|
||||
<param index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
Changes the visibility of a right thumbstick element. Default is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
@ -78,6 +78,7 @@ ios_lib = [
|
||||
"keyboard_input_view.mm",
|
||||
"key_mapping_ios.mm",
|
||||
"ios_terminal_logger.mm",
|
||||
"virtual_controller_ios.mm",
|
||||
]
|
||||
|
||||
env_ios = env.Clone()
|
||||
|
@ -184,6 +184,8 @@ void JoypadIOS::start_processing() {
|
||||
} else {
|
||||
[self addiOSJoypad:controller];
|
||||
}
|
||||
|
||||
OS_IOS::get_singleton()->controller_connected();
|
||||
}
|
||||
|
||||
- (void)controllerWasDisconnected:(NSNotification *)notification {
|
||||
@ -203,6 +205,8 @@ void JoypadIOS::start_processing() {
|
||||
// and remove it from our dictionary
|
||||
[self.connectedJoypads removeObjectForKey:key];
|
||||
}
|
||||
|
||||
OS_IOS::get_singleton()->controller_disconnected();
|
||||
}
|
||||
|
||||
- (GCControllerPlayerIndex)getFreePlayerIndex {
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#import "ios.h"
|
||||
#import "joypad_ios.h"
|
||||
#import "virtual_controller_ios.h"
|
||||
|
||||
#import "drivers/coreaudio/audio_driver_coreaudio.h"
|
||||
#include "drivers/unix/os_unix.h"
|
||||
@ -62,6 +63,8 @@ private:
|
||||
|
||||
MainLoop *main_loop = nullptr;
|
||||
|
||||
IOSVirtualController *virtual_controller = nullptr;
|
||||
|
||||
virtual void initialize_core() override;
|
||||
virtual void initialize() override;
|
||||
|
||||
@ -127,11 +130,17 @@ public:
|
||||
|
||||
virtual bool _check_internal_feature_support(const String &p_feature) override;
|
||||
|
||||
virtual VirtualController *get_virtual_controller() const override;
|
||||
|
||||
void on_focus_out();
|
||||
void on_focus_in();
|
||||
|
||||
void on_enter_background();
|
||||
void on_exit_background();
|
||||
|
||||
void controller_connected();
|
||||
|
||||
void controller_disconnected();
|
||||
};
|
||||
|
||||
#endif // IOS_ENABLED
|
||||
|
@ -131,9 +131,15 @@ void OS_IOS::initialize_modules() {
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios));
|
||||
|
||||
joypad_ios = memnew(JoypadIOS);
|
||||
|
||||
virtual_controller = memnew(IOSVirtualController);
|
||||
}
|
||||
|
||||
void OS_IOS::deinitialize_modules() {
|
||||
if (virtual_controller) {
|
||||
memdelete(virtual_controller);
|
||||
}
|
||||
|
||||
if (joypad_ios) {
|
||||
memdelete(joypad_ios);
|
||||
}
|
||||
@ -180,6 +186,10 @@ void OS_IOS::start() {
|
||||
if (joypad_ios) {
|
||||
joypad_ios->start_processing();
|
||||
}
|
||||
|
||||
if (virtual_controller) {
|
||||
virtual_controller->update_state();
|
||||
}
|
||||
}
|
||||
|
||||
void OS_IOS::finalize() {
|
||||
@ -591,6 +601,10 @@ bool OS_IOS::_check_internal_feature_support(const String &p_feature) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VirtualController *OS_IOS::get_virtual_controller() const {
|
||||
return virtual_controller;
|
||||
}
|
||||
|
||||
void OS_IOS::on_focus_out() {
|
||||
if (is_focused) {
|
||||
is_focused = false;
|
||||
@ -647,4 +661,16 @@ void OS_IOS::on_exit_background() {
|
||||
}
|
||||
}
|
||||
|
||||
void OS_IOS::controller_connected() {
|
||||
if (virtual_controller) {
|
||||
virtual_controller->controller_connected();
|
||||
}
|
||||
}
|
||||
|
||||
void OS_IOS::controller_disconnected() {
|
||||
if (virtual_controller) {
|
||||
virtual_controller->controller_disconnected();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IOS_ENABLED
|
||||
|
80
platform/ios/virtual_controller_ios.h
Normal file
80
platform/ios/virtual_controller_ios.h
Normal file
@ -0,0 +1,80 @@
|
||||
/**************************************************************************/
|
||||
/* virtual_controller_ios.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#import "core/input/virtual_controller.h"
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
class IOSVirtualController : public VirtualController {
|
||||
private:
|
||||
#if defined(__IPHONE_15_0)
|
||||
API_AVAILABLE(ios(15.0))
|
||||
GCVirtualController *gcv_controller;
|
||||
#endif
|
||||
|
||||
public:
|
||||
IOSVirtualController();
|
||||
~IOSVirtualController();
|
||||
|
||||
virtual void enable() override;
|
||||
virtual void disable() override;
|
||||
virtual bool is_enabled() override;
|
||||
virtual void set_enabled_left_thumbstick(bool p_enabled) override;
|
||||
virtual bool is_enabled_left_thumbstick() override;
|
||||
virtual void set_enabled_right_thumbstick(bool p_enabled) override;
|
||||
virtual bool is_enabled_right_thumbstick() override;
|
||||
virtual void set_enabled_button_a(bool p_enabled) override;
|
||||
virtual bool is_enabled_button_a() override;
|
||||
virtual void set_enabled_button_b(bool p_enabled) override;
|
||||
virtual bool is_enabled_button_b() override;
|
||||
virtual void set_enabled_button_x(bool p_enabled) override;
|
||||
virtual bool is_enabled_button_x() override;
|
||||
virtual void set_enabled_button_y(bool p_enabled) override;
|
||||
virtual bool is_enabled_button_y() override;
|
||||
|
||||
void controller_connected();
|
||||
void controller_disconnected();
|
||||
void update_state();
|
||||
|
||||
private:
|
||||
void connect_controller();
|
||||
void disconnect_controller();
|
||||
void initialize();
|
||||
void elements_changed(GCInputElementName name, bool hidden);
|
||||
void read_project_settings();
|
||||
|
||||
private:
|
||||
bool enabled = false;
|
||||
bool enabled_left_thumbstick = true;
|
||||
bool enabled_right_thumbstick = true;
|
||||
bool enabled_button_a = true;
|
||||
bool enabled_button_b = true;
|
||||
bool enabled_button_x = true;
|
||||
bool enabled_button_y = true;
|
||||
};
|
246
platform/ios/virtual_controller_ios.mm
Normal file
246
platform/ios/virtual_controller_ios.mm
Normal file
@ -0,0 +1,246 @@
|
||||
/**************************************************************************/
|
||||
/* virtual_controller_ios.mm */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#import "virtual_controller_ios.h"
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
IOSVirtualController::IOSVirtualController() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
IOSVirtualController::~IOSVirtualController() {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
gcv_controller = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::initialize() {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
if (!gcv_controller) {
|
||||
read_project_settings();
|
||||
|
||||
GCVirtualControllerConfiguration *config = [[GCVirtualControllerConfiguration alloc] init];
|
||||
|
||||
NSMutableSet *elements = [[NSMutableSet alloc] init];
|
||||
|
||||
if (is_enabled_left_thumbstick()) {
|
||||
[elements addObject:GCInputLeftThumbstick];
|
||||
}
|
||||
if (is_enabled_right_thumbstick()) {
|
||||
[elements addObject:GCInputRightThumbstick];
|
||||
}
|
||||
if (is_enabled_button_a()) {
|
||||
[elements addObject:GCInputButtonA];
|
||||
}
|
||||
if (is_enabled_button_b()) {
|
||||
[elements addObject:GCInputButtonB];
|
||||
}
|
||||
if (is_enabled_button_x()) {
|
||||
[elements addObject:GCInputButtonX];
|
||||
}
|
||||
if (is_enabled_button_y()) {
|
||||
[elements addObject:GCInputButtonY];
|
||||
}
|
||||
|
||||
config.elements = elements;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
gcv_controller = [[GCVirtualController alloc] initWithConfiguration:config];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::read_project_settings() {
|
||||
enabled = GLOBAL_GET("input_devices/virtual_controller/ios/enable_controller");
|
||||
enabled_left_thumbstick = GLOBAL_GET("input_devices/virtual_controller/ios/enable_left_thumbstick");
|
||||
enabled_right_thumbstick = GLOBAL_GET("input_devices/virtual_controller/ios/enable_right_thumbstick");
|
||||
enabled_button_a = GLOBAL_GET("input_devices/virtual_controller/ios/enable_button_a");
|
||||
enabled_button_b = GLOBAL_GET("input_devices/virtual_controller/ios/enable_button_b");
|
||||
enabled_button_x = GLOBAL_GET("input_devices/virtual_controller/ios/enable_button_x");
|
||||
enabled_button_y = GLOBAL_GET("input_devices/virtual_controller/ios/enable_button_y");
|
||||
}
|
||||
|
||||
void IOSVirtualController::elements_changed(GCInputElementName name, bool hidden) {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (gcv_controller) {
|
||||
[gcv_controller updateConfigurationForElement:name
|
||||
configuration:^(GCVirtualControllerElementConfiguration *configuration) {
|
||||
configuration.hidden = hidden;
|
||||
return configuration;
|
||||
}];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::enable() {
|
||||
enabled = true;
|
||||
update_state();
|
||||
}
|
||||
|
||||
void IOSVirtualController::disable() {
|
||||
enabled = false;
|
||||
update_state();
|
||||
}
|
||||
|
||||
void IOSVirtualController::update_state() {
|
||||
if (is_enabled()) {
|
||||
connect_controller();
|
||||
} else {
|
||||
disconnect_controller();
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void IOSVirtualController::connect_controller() {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (GCController.controllers.count == 0 && gcv_controller != nil) {
|
||||
[gcv_controller connectWithReplyHandler:nil];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::disconnect_controller() {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (gcv_controller) {
|
||||
[gcv_controller disconnect];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::controller_connected() {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
if (gcv_controller != nil) {
|
||||
BOOL hasPhysicalController = NO;
|
||||
for (GCController *controller in GCController.controllers) {
|
||||
if (controller != gcv_controller.controller) {
|
||||
hasPhysicalController = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasPhysicalController) {
|
||||
disconnect_controller();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::controller_disconnected() {
|
||||
if (is_enabled()) {
|
||||
connect_controller();
|
||||
}
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_left_thumbstick(bool p_enabled) {
|
||||
if (enabled_left_thumbstick != p_enabled) {
|
||||
enabled_left_thumbstick = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputLeftThumbstick, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_left_thumbstick() {
|
||||
return enabled_left_thumbstick;
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_right_thumbstick(bool p_enabled) {
|
||||
if (enabled_right_thumbstick != p_enabled) {
|
||||
enabled_right_thumbstick = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputRightThumbstick, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_right_thumbstick() {
|
||||
return enabled_right_thumbstick;
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_button_a(bool p_enabled) {
|
||||
if (enabled_button_a != p_enabled) {
|
||||
enabled_button_a = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputButtonA, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_button_a() {
|
||||
return enabled_button_a;
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_button_b(bool p_enabled) {
|
||||
if (enabled_button_b != p_enabled) {
|
||||
enabled_button_b = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputButtonB, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_button_b() {
|
||||
return enabled_button_b;
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_button_x(bool p_enabled) {
|
||||
if (enabled_button_x != p_enabled) {
|
||||
enabled_button_x = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputButtonX, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_button_x() {
|
||||
return enabled_button_x;
|
||||
}
|
||||
|
||||
void IOSVirtualController::set_enabled_button_y(bool p_enabled) {
|
||||
if (enabled_button_y != p_enabled) {
|
||||
enabled_button_y = p_enabled;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
elements_changed(GCInputButtonY, !p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IOSVirtualController::is_enabled_button_y() {
|
||||
return enabled_button_y;
|
||||
}
|
Loading…
Reference in New Issue
Block a user