mirror of https://github.com/godotengine/godot
Fix custom cursor flickering in web builds
Implement caching of the custom cursor state in `DisplayServerWeb` to prevent redundant updates to the browser's cursor. This change computes a hash based on the cursor resource, shape, and hotspot, and only updates the browser's cursor when the hash changes. This mitigates the flickering observed in web exports when `set_custom_mouse_cursor()` is called every frame.
This commit is contained in:
parent
e7ac8e45a3
commit
6dc2a886e7
|
|
@ -514,8 +514,42 @@ DisplayServer::CursorShape DisplayServerWeb::cursor_get_shape() const {
|
||||||
return cursor_shape;
|
return cursor_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t DisplayServerWeb::_compute_cursor_hash(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) const {
|
||||||
|
if (!p_cursor.is_valid()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t seed = 0;
|
||||||
|
|
||||||
|
// Local functor for combining hash values.
|
||||||
|
struct Combiner {
|
||||||
|
uint64_t &seed;
|
||||||
|
|
||||||
|
void combine(uint64_t value) const {
|
||||||
|
// This uses a 64-bit constant akin to `boost::hash_combine`.
|
||||||
|
seed ^= value + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Combiner combiner{ seed };
|
||||||
|
|
||||||
|
combiner.combine(p_cursor->get_instance_id());
|
||||||
|
combiner.combine(static_cast<uint64_t>(p_shape));
|
||||||
|
combiner.combine(static_cast<uint64_t>(static_cast<int>(p_hotspot.x)));
|
||||||
|
combiner.combine(static_cast<uint64_t>(static_cast<int>(p_hotspot.y)));
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayServerWeb::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
void DisplayServerWeb::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
|
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
|
||||||
|
|
||||||
|
uint64_t new_cursor_hash = _compute_cursor_hash(p_cursor, p_shape, p_hotspot);
|
||||||
|
if (new_cursor_hash == current_cursor_hash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_cursor_hash = new_cursor_hash;
|
||||||
|
|
||||||
if (p_cursor.is_valid()) {
|
if (p_cursor.is_valid()) {
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ private:
|
||||||
uint64_t last_click_ms = 0;
|
uint64_t last_click_ms = 0;
|
||||||
MouseButton last_click_button_index = MouseButton::NONE;
|
MouseButton last_click_button_index = MouseButton::NONE;
|
||||||
|
|
||||||
|
uint64_t current_cursor_hash;
|
||||||
|
uint64_t _compute_cursor_hash(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) const;
|
||||||
|
|
||||||
bool ime_active = false;
|
bool ime_active = false;
|
||||||
bool ime_started = false;
|
bool ime_started = false;
|
||||||
String ime_text;
|
String ime_text;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue