Repository: godotengine/godot
File: core/input/input.cpp (C++)

Code before:
		return joy_vibration[p_device].timestamp;
	} else {
		return 0;
	}
}

float Input::get_joy_vibration_duration(int p_device) {
	if (joy_vibration.has(p_device)) {
		return joy_vibration[p_device].duration;
	} else {
		return 0.f;
	}
}

float Input::get_joy_vibration_remaining_duration(int p_device) {
	_THREAD_SAFE_METHOD_
	const Joypad *joypad = joy_names.getptr(p_device);
	if (joypad == nullptr || !joypad->has_vibration) {
		return 0.f;
	}
	const VibrationInfo *vibration = joy_vibration.getptr(p_device);
	if (vibration == nullptr || (vibration->weak_magnitude == 0.f && vibration->strong_magnitude == 0.f) || vibration->duration < 0.f) {
		return 0.f;
	}
	if (vibration->duration == 0.f) {
		return -1.f; // The vibration plays indefinitely.
	}
	return MAX(vibration->duration - (OS::get_singleton()->get_ticks_usec() - vibration->timestamp) / 1e6, 0.f);
}

bool Input::is_joy_vibrating(int p_device) {
	return get_joy_vibration_remaining_duration(p_device) != 0.f;
}

bool Input::has_joy_vibration(int p_device) const {
	_THREAD_SAFE_METHOD_
	const Joypad *joypad = joy_names.getptr(p_device);
	return joypad != nullptr && joypad->has_vibration;
}

static String _hex_str(uint8_t p_byte) {
	static const char *dict = "0123456789abcdef";
	char ret[3];
	ret[2] = 0;

	ret[0] = dict[p_byte >> 4];
	ret[1] = dict[p_byte & 0xf];

	return ret;
}


Review comment (bug):
It's failing here, probably because `ClassDB::bind_method` isn't being used?

<img width="1352" height="358" alt="Image" src="https://github.com/user-attachments/assets/de47a1a3-3b40-48a6-8b7a-b7f0962826fb" />

Code after:

Vector2 Input::get_joy_vibration_strength(int p_device) {
	if (joy_vibration.has(p_device)) {
		return Vector2(joy_vibration[p_device].weak_magnitude, joy_vibration[p_device].strong_magnitude);
	} else {
		return Vector2(0, 0);
	}
}

uint64_t Input::get_joy_vibration_timestamp(int p_device) {
	if (joy_vibration.has(p_device)) {
		return joy_vibration[p_device].timestamp;
	} else {
		return 0;
	}
}

float Input::get_joy_vibration_duration(int p_device) {
	if (joy_vibration.has(p_device)) {
		return joy_vibration[p_device].duration;
	} else {
		return 0.f;
	}
}

float Input::get_joy_vibration_remaining_duration(int p_device) {
	_THREAD_SAFE_METHOD_
	const Joypad *joypad = joy_names.getptr(p_device);
	if (joypad == nullptr || !joypad->has_vibration) {
		return 0.f;
	}
	const VibrationInfo *vibration = joy_vibration.getptr(p_device);
	if (vibration == nullptr || (vibration->weak_magnitude == 0.f && vibration->strong_magnitude == 0.f) || vibration->duration < 0.f) {
		return 0.f;
	}
	float vibration_duration = vibration->duration;
	if (vibration_duration > 0xFFFF / 1000.f || vibration_duration == 0.f) {
		vibration_duration = 0xFFFF / 1000.f; // SDL_MAX_RUMBLE_DURATION_MS / 1000.f
	}
	return MAX(vibration_duration - (OS::get_singleton()->get_ticks_usec() - vibration->timestamp) / 1e6, 0.f);
}

bool Input::is_joy_vibrating(int p_device) {
	return get_joy_vibration_remaining_duration(p_device) > 0.0f;
}

bool Input::has_joy_vibration(int p_device) const {
	_THREAD_SAFE_METHOD_
	const Joypad *joypad = joy_names.getptr(p_device);
	return joypad != nullptr && joypad->has_vibration;
}