@@ -147,10 +147,27 @@ void Input::_bind_methods() {
147147 ClassDB::bind_method (D_METHOD (" get_accelerometer" ), &Input::get_accelerometer);
148148 ClassDB::bind_method (D_METHOD (" get_magnetometer" ), &Input::get_magnetometer);
149149 ClassDB::bind_method (D_METHOD (" get_gyroscope" ), &Input::get_gyroscope);
150+ ClassDB::bind_method (D_METHOD (" is_joy_accelerometer_enabled" , " device" ), &Input::is_joy_accelerometer_enabled);
151+ ClassDB::bind_method (D_METHOD (" is_joy_gyroscope_enabled" , " device" ), &Input::is_joy_gyroscope_enabled);
152+ ClassDB::bind_method (D_METHOD (" get_joy_accelerometer" , " device" ), &Input::get_joy_accelerometer);
153+ ClassDB::bind_method (D_METHOD (" get_joy_gravity" , " device" ), &Input::get_joy_gravity);
154+ ClassDB::bind_method (D_METHOD (" get_joy_gyroscope" , " device" ), &Input::get_joy_gyroscope);
155+ ClassDB::bind_method (D_METHOD (" start_joy_motion_calibration" , " device" ), &Input::start_joy_motion_calibration);
156+ ClassDB::bind_method (D_METHOD (" step_joy_motion_calibration" , " device" ), &Input::step_joy_motion_calibration);
157+ ClassDB::bind_method (D_METHOD (" stop_joy_motion_calibration" , " device" ), &Input::stop_joy_motion_calibration);
158+ ClassDB::bind_method (D_METHOD (" clear_joy_motion_calibration" , " device" ), &Input::clear_joy_motion_calibration);
159+ ClassDB::bind_method (D_METHOD (" get_joy_motion_calibration" , " device" ), &Input::get_joy_motion_calibration);
160+ ClassDB::bind_method (D_METHOD (" set_joy_motion_calibration" , " device" , " calibration_info" ), &Input::set_joy_motion_calibration);
161+ ClassDB::bind_method (D_METHOD (" is_joy_motion_calibrated" , " device" ), &Input::is_joy_motion_calibrated);
162+ ClassDB::bind_method (D_METHOD (" is_joy_motion_calibrating" , " device" ), &Input::is_joy_motion_calibrating);
150163 ClassDB::bind_method (D_METHOD (" set_gravity" , " value" ), &Input::set_gravity);
151164 ClassDB::bind_method (D_METHOD (" set_accelerometer" , " value" ), &Input::set_accelerometer);
152165 ClassDB::bind_method (D_METHOD (" set_magnetometer" , " value" ), &Input::set_magnetometer);
153166 ClassDB::bind_method (D_METHOD (" set_gyroscope" , " value" ), &Input::set_gyroscope);
167+ ClassDB::bind_method (D_METHOD (" set_joy_accelerometer_enabled" , " device" , " enable" ), &Input::set_joy_accelerometer_enabled);
168+ ClassDB::bind_method (D_METHOD (" set_joy_gyroscope_enabled" , " device" , " enable" ), &Input::set_joy_gyroscope_enabled);
169+ ClassDB::bind_method (D_METHOD (" has_joy_accelerometer" , " device" ), &Input::has_joy_accelerometer);
170+ ClassDB::bind_method (D_METHOD (" has_joy_gyroscope" , " device" ), &Input::has_joy_gyroscope);
154171 ClassDB::bind_method (D_METHOD (" get_last_mouse_velocity" ), &Input::get_last_mouse_velocity);
155172 ClassDB::bind_method (D_METHOD (" get_last_mouse_screen_velocity" ), &Input::get_last_mouse_screen_velocity);
156173 ClassDB::bind_method (D_METHOD (" get_mouse_button_mask" ), &Input::get_mouse_button_mask);
@@ -731,6 +748,202 @@ Vector3 Input::get_gyroscope() const {
731748 return gyroscope;
732749}
733750
751+ bool Input::is_joy_accelerometer_enabled (int p_device) const {
752+ _THREAD_SAFE_METHOD_
753+ return joy_motion.has (p_device) && joy_motion[p_device].accelerometer_enabled ;
754+ }
755+
756+ bool Input::is_joy_gyroscope_enabled (int p_device) const {
757+ _THREAD_SAFE_METHOD_
758+ return joy_motion.has (p_device) && joy_motion[p_device].gyroscope_enabled ;
759+ }
760+
761+ Vector3 Input::get_joy_accelerometer (int p_device) const {
762+ _THREAD_SAFE_METHOD_
763+ if (!joy_motion.has (p_device)) {
764+ return Vector3 ();
765+ }
766+
767+ if (!joy_motion[p_device].calibration .calibrated ) {
768+ return joy_motion[p_device].accelerometer ;
769+ }
770+
771+ const MotionInfo &motion = joy_motion[p_device];
772+ // Calibrated accelerometer doesn't include gravity
773+ Vector3 value = (motion.accelerometer - motion.gravity ) - motion.calibration .accelerometer_offset ;
774+ if (std::abs (value.x ) < motion.calibration .accelerometer_deadzone ) {
775+ value.x = 0 ;
776+ }
777+ if (std::abs (value.y ) < motion.calibration .accelerometer_deadzone ) {
778+ value.y = 0 ;
779+ }
780+ if (std::abs (value.z ) < motion.calibration .accelerometer_deadzone ) {
781+ value.z = 0 ;
782+ }
783+ return value;
784+ }
785+
786+ Vector3 Input::get_joy_gravity (int p_device) const {
787+ _THREAD_SAFE_METHOD_
788+ if (!joy_motion.has (p_device)) {
789+ return Vector3 ();
790+ }
791+ // Does gravity need calibration?
792+ return joy_motion[p_device].gravity ;
793+ }
794+
795+ Vector3 Input::get_joy_gyroscope (int p_device) const {
796+ _THREAD_SAFE_METHOD_
797+ if (!joy_motion.has (p_device)) {
798+ return Vector3 ();
799+ }
800+
801+ if (!joy_motion[p_device].calibration .calibrated ) {
802+ return joy_motion[p_device].gyroscope ;
803+ }
804+
805+ const MotionInfo &motion = joy_motion[p_device];
806+ Vector3 value = motion.gyroscope - motion.calibration .accelerometer_offset ;
807+ if (std::abs (value.x ) < motion.calibration .gyroscope_deadzone ) {
808+ value.x = 0 ;
809+ }
810+ if (std::abs (value.y ) < motion.calibration .gyroscope_deadzone ) {
811+ value.y = 0 ;
812+ }
813+ if (std::abs (value.z ) < motion.calibration .gyroscope_deadzone ) {
814+ value.z = 0 ;
815+ }
816+ return value;
817+ }
818+
819+ #define CALIBRATION_SETUP \
820+ if (!joy_motion.has(p_device)) { \
821+ return ; \
822+ } \
823+ auto &calibration = joy_motion[p_device].calibration;
824+
825+ #define CALIBRATION_SETUP_RETURN (m_return ) \
826+ if (!joy_motion.has(p_device)) { \
827+ return m_return; \
828+ } \
829+ auto &calibration = joy_motion[p_device].calibration;
830+
831+ #define CALIBRATE_SENSOR (m_sensor ) \
832+ vector_sum = Vector3(); \
833+ for (Vector3 step : calibration.m_sensor##_steps) { \
834+ vector_sum += step; \
835+ } \
836+ vector_sum /= calibration.m_sensor##_steps.size(); \
837+ \
838+ deadzone = 0 .0f ; \
839+ for (Vector3 step : calibration.m_sensor##_steps) { \
840+ deadzone = MAX (deadzone, (step - vector_sum).length ()); \
841+ } \
842+ \
843+ calibration.m_sensor##_offset = vector_sum; \
844+ calibration.m_sensor##_deadzone = deadzone; \
845+ calibration.m_sensor##_steps.clear();
846+
847+ void Input::start_joy_motion_calibration (int p_device) {
848+ _THREAD_SAFE_METHOD_
849+ CALIBRATION_SETUP;
850+
851+ ERR_FAIL_COND_MSG (calibration.in_progress , " Calibration already in progress." );
852+
853+ clear_joy_motion_calibration (p_device);
854+ calibration.in_progress = true ;
855+ }
856+
857+ void Input::step_joy_motion_calibration (int p_device) {
858+ _THREAD_SAFE_METHOD_
859+ CALIBRATION_SETUP;
860+
861+ ERR_FAIL_COND_MSG (!calibration.in_progress , " Calibration hasn't been started." );
862+
863+ const MotionInfo &motion = joy_motion[p_device];
864+ calibration.accelerometer_steps .push_back (motion.accelerometer - motion.gravity );
865+ calibration.gyroscope_steps .push_back (motion.gyroscope );
866+ }
867+
868+ void Input::stop_joy_motion_calibration (int p_device) {
869+ _THREAD_SAFE_METHOD_
870+ CALIBRATION_SETUP;
871+
872+ ERR_FAIL_COND_MSG (!calibration.in_progress , " Calibration hasn't been started." );
873+
874+ if (calibration.accelerometer_steps .size () < 10 ) {
875+ WARN_PRINT_ED (" Not enough joypad motion sensors calibration steps, "
876+ " you should call Input.step_joy_motion_calibration() at least 10 times." );
877+ }
878+
879+ Vector3 vector_sum;
880+ float deadzone = 0 .0f ;
881+
882+ CALIBRATE_SENSOR (accelerometer);
883+ CALIBRATE_SENSOR (gyroscope);
884+
885+ calibration.in_progress = false ;
886+ calibration.calibrated = true ;
887+ }
888+
889+ void Input::clear_joy_motion_calibration (int p_device) {
890+ _THREAD_SAFE_METHOD_
891+ CALIBRATION_SETUP;
892+
893+ // Calibration might be in progress and the user might want to reset the progress,
894+ // so no need to stop the calibration.
895+ // calibration.in_progress = false;
896+ calibration.accelerometer_steps .clear ();
897+ calibration.gyroscope_steps .clear ();
898+ calibration.accelerometer_offset = Vector3 ();
899+ calibration.gyroscope_offset = Vector3 ();
900+ calibration.accelerometer_deadzone = 0 .0f ;
901+ calibration.gyroscope_deadzone = 0 .0f ;
902+ calibration.calibrated = false ;
903+ }
904+
905+ Dictionary Input::get_joy_motion_calibration (int p_device) const {
906+ _THREAD_SAFE_METHOD_
907+ CALIBRATION_SETUP_RETURN ({});
908+
909+ if (!calibration.calibrated ) {
910+ return {};
911+ }
912+
913+ Dictionary result;
914+ result[" accelerometer_offset" ] = calibration.accelerometer_offset ;
915+ result[" accelerometer_deadzone" ] = calibration.accelerometer_deadzone ;
916+ result[" gyroscope_offset" ] = calibration.gyroscope_offset ;
917+ result[" gyroscope_deadzone" ] = calibration.gyroscope_deadzone ;
918+ return result;
919+ }
920+
921+ void Input::set_joy_motion_calibration (int p_device, Dictionary p_calibration_info) {
922+ _THREAD_SAFE_METHOD_
923+ CALIBRATION_SETUP;
924+
925+ ERR_FAIL_COND_MSG (calibration.in_progress , " Calibration already in progress." );
926+
927+ calibration.accelerometer_offset = p_calibration_info[" accelerometer_offset" ];
928+ calibration.accelerometer_deadzone = p_calibration_info[" accelerometer_deadzone" ];
929+ calibration.gyroscope_offset = p_calibration_info[" gyroscope_offset" ];
930+ calibration.gyroscope_deadzone = p_calibration_info[" gyroscope_deadzone" ];
931+ calibration.in_progress = false ;
932+ calibration.calibrated = true ;
933+ }
934+
935+ bool Input::is_joy_motion_calibrated (int p_device) const {
936+ _THREAD_SAFE_METHOD_
937+ CALIBRATION_SETUP_RETURN (false );
938+ return calibration.calibrated ;
939+ }
940+
941+ bool Input::is_joy_motion_calibrating (int p_device) const {
942+ _THREAD_SAFE_METHOD_
943+ CALIBRATION_SETUP_RETURN (false );
944+ return calibration.in_progress ;
945+ }
946+
734947void Input::_parse_input_event_impl (const Ref<InputEvent> &p_event, bool p_is_emulated) {
735948 // This function does the final delivery of the input event to user land.
736949 // Regardless where the event came from originally, this has to happen on the main thread.
@@ -986,6 +1199,70 @@ void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) {
9861199 _joy_axis[c] = p_value;
9871200}
9881201
1202+ void Input::set_joy_features (int p_device, JoypadFeatures *p_features) {
1203+ if (!joy_names.has (p_device)) {
1204+ return ;
1205+ }
1206+ joy_names[p_device].features = p_features;
1207+ _update_joypad_features (p_device);
1208+ }
1209+
1210+ bool Input::set_joy_accelerometer_enabled (int p_device, bool p_enable) {
1211+ _THREAD_SAFE_METHOD_
1212+ if (!joy_names.has (p_device) || joy_names[p_device].features == nullptr ) {
1213+ return false ;
1214+ }
1215+ bool enabled = joy_names[p_device].features ->set_joy_accelerometer_enabled (p_enable);
1216+ joy_motion[p_device].accelerometer = Vector3 ();
1217+ joy_motion[p_device].accelerometer_enabled = enabled;
1218+ return enabled;
1219+ }
1220+
1221+ bool Input::set_joy_gyroscope_enabled (int p_device, bool p_enable) {
1222+ _THREAD_SAFE_METHOD_
1223+ if (!joy_names.has (p_device) || joy_names[p_device].features == nullptr ) {
1224+ return false ;
1225+ }
1226+ bool enabled = joy_names[p_device].features ->set_joy_gyroscope_enabled (p_enable);
1227+ joy_motion[p_device].gyroscope = Vector3 ();
1228+ joy_motion[p_device].gyroscope_enabled = enabled;
1229+ return enabled;
1230+ }
1231+
1232+ void Input::set_joy_accelerometer (int p_device, const Vector3 &p_value) {
1233+ _THREAD_SAFE_METHOD_
1234+ if (!joy_motion.has (p_device)) {
1235+ return ;
1236+ }
1237+ joy_motion[p_device].accelerometer = p_value;
1238+ }
1239+
1240+ void Input::set_joy_gravity (int p_device, const Vector3 &p_value) {
1241+ _THREAD_SAFE_METHOD_
1242+ if (!joy_motion.has (p_device)) {
1243+ return ;
1244+ }
1245+ joy_motion[p_device].gravity = p_value;
1246+ }
1247+
1248+ void Input::set_joy_gyroscope (int p_device, const Vector3 &p_value) {
1249+ _THREAD_SAFE_METHOD_
1250+ if (!joy_motion.has (p_device)) {
1251+ return ;
1252+ }
1253+ joy_motion[p_device].gyroscope = p_value;
1254+ }
1255+
1256+ bool Input::has_joy_accelerometer (int p_device) const {
1257+ _THREAD_SAFE_METHOD_
1258+ return joy_motion.has (p_device) && joy_motion[p_device].has_accelerometer ;
1259+ }
1260+
1261+ bool Input::has_joy_gyroscope (int p_device) const {
1262+ _THREAD_SAFE_METHOD_
1263+ return joy_motion.has (p_device) && joy_motion[p_device].has_gyroscope ;
1264+ }
1265+
9891266void Input::start_joy_vibration (int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) {
9901267 _THREAD_SAFE_METHOD_
9911268 if (p_weak_magnitude < 0 .f || p_weak_magnitude > 1 .f || p_strong_magnitude < 0 .f || p_strong_magnitude > 1 .f ) {
@@ -1478,6 +1755,18 @@ void Input::_update_action_cache(const StringName &p_action_name, ActionState &r
14781755 }
14791756}
14801757
1758+ void Input::_update_joypad_features (int p_device) {
1759+ if (!joy_names.has (p_device) || joy_names[p_device].features == nullptr ) {
1760+ return ;
1761+ }
1762+ if (joy_names[p_device].features ->has_joy_accelerometer ()) {
1763+ joy_motion[p_device].has_accelerometer = true ;
1764+ }
1765+ if (joy_names[p_device].features ->has_joy_gyroscope ()) {
1766+ joy_motion[p_device].has_gyroscope = true ;
1767+ }
1768+ }
1769+
14811770Input::JoyEvent Input::_get_mapped_button_event (const JoyDeviceMapping &mapping, JoyButton p_button) {
14821771 JoyEvent event;
14831772
0 commit comments