Merge pull request #92702 from kleonc/cursor_image_from_atlas_texture_fix
Fix creating cursor image from `AtlasTexture`
This commit is contained in:
commit
e52658643d
|
@ -1018,8 +1018,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor
|
||||||
wayland_thread.cursor_shape_clear_custom_image(p_shape);
|
wayland_thread.cursor_shape_clear_custom_image(p_shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect2 atlas_rect;
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect);
|
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
|
|
||||||
CustomCursor &cursor = custom_cursors[p_shape];
|
CustomCursor &cursor = custom_cursors[p_shape];
|
||||||
|
|
|
@ -3108,8 +3108,7 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu
|
||||||
cursors_cache.erase(p_shape);
|
cursors_cache.erase(p_shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect2 atlas_rect;
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect);
|
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
Vector2i texture_size = image->get_size();
|
Vector2i texture_size = image->get_size();
|
||||||
|
|
||||||
|
@ -3127,13 +3126,8 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu
|
||||||
cursor_image->pixels = (XcursorPixel *)memalloc(size);
|
cursor_image->pixels = (XcursorPixel *)memalloc(size);
|
||||||
|
|
||||||
for (XcursorPixel index = 0; index < image_size; index++) {
|
for (XcursorPixel index = 0; index < image_size; index++) {
|
||||||
int row_index = floor(index / texture_size.width) + atlas_rect.position.y;
|
int row_index = floor(index / texture_size.width);
|
||||||
int column_index = (index % int(texture_size.width)) + atlas_rect.position.x;
|
int column_index = index % int(texture_size.width);
|
||||||
|
|
||||||
if (atlas_rect.has_area()) {
|
|
||||||
column_index = MIN(column_index, atlas_rect.size.width - 1);
|
|
||||||
row_index = MIN(row_index, atlas_rect.size.height - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
*(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32();
|
*(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2845,8 +2845,7 @@ void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor,
|
||||||
cursors_cache.erase(p_shape);
|
cursors_cache.erase(p_shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect2 atlas_rect;
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect);
|
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
Vector2i texture_size = image->get_size();
|
Vector2i texture_size = image->get_size();
|
||||||
|
|
||||||
|
@ -2868,13 +2867,8 @@ void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor,
|
||||||
int len = int(texture_size.width * texture_size.height);
|
int len = int(texture_size.width * texture_size.height);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
int row_index = floor(i / texture_size.width) + atlas_rect.position.y;
|
int row_index = floor(i / texture_size.width);
|
||||||
int column_index = (i % int(texture_size.width)) + atlas_rect.position.x;
|
int column_index = i % int(texture_size.width);
|
||||||
|
|
||||||
if (atlas_rect.has_area()) {
|
|
||||||
column_index = MIN(column_index, atlas_rect.size.width - 1);
|
|
||||||
row_index = MIN(row_index, atlas_rect.size.height - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t color = image->get_pixel(column_index, row_index).to_argb32();
|
uint32_t color = image->get_pixel(column_index, row_index).to_argb32();
|
||||||
|
|
||||||
|
|
|
@ -517,19 +517,10 @@ DisplayServer::CursorShape DisplayServerWeb::cursor_get_shape() const {
|
||||||
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);
|
||||||
if (p_cursor.is_valid()) {
|
if (p_cursor.is_valid()) {
|
||||||
Rect2 atlas_rect;
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect);
|
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
Vector2i texture_size = image->get_size();
|
Vector2i texture_size = image->get_size();
|
||||||
|
|
||||||
if (atlas_rect.has_area()) {
|
|
||||||
image->crop_from_point(
|
|
||||||
atlas_rect.position.x,
|
|
||||||
atlas_rect.position.y,
|
|
||||||
texture_size.width,
|
|
||||||
texture_size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->get_format() != Image::FORMAT_RGBA8) {
|
if (image->get_format() != Image::FORMAT_RGBA8) {
|
||||||
image->convert(Image::FORMAT_RGBA8);
|
image->convert(Image::FORMAT_RGBA8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2408,8 +2408,7 @@ void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor
|
||||||
cursors_cache.erase(p_shape);
|
cursors_cache.erase(p_shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect2 atlas_rect;
|
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot);
|
||||||
Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect);
|
|
||||||
ERR_FAIL_COND(image.is_null());
|
ERR_FAIL_COND(image.is_null());
|
||||||
Vector2i texture_size = image->get_size();
|
Vector2i texture_size = image->get_size();
|
||||||
|
|
||||||
|
@ -2437,13 +2436,9 @@ void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor
|
||||||
|
|
||||||
bool fully_transparent = true;
|
bool fully_transparent = true;
|
||||||
for (UINT index = 0; index < image_size; index++) {
|
for (UINT index = 0; index < image_size; index++) {
|
||||||
int row_index = floor(index / texture_size.width) + atlas_rect.position.y;
|
int row_index = floor(index / texture_size.width);
|
||||||
int column_index = (index % int(texture_size.width)) + atlas_rect.position.x;
|
int column_index = index % int(texture_size.width);
|
||||||
|
|
||||||
if (atlas_rect.has_area()) {
|
|
||||||
column_index = MIN(column_index, atlas_rect.size.width - 1);
|
|
||||||
row_index = MIN(row_index, atlas_rect.size.height - 1);
|
|
||||||
}
|
|
||||||
const Color &c = image->get_pixel(column_index, row_index);
|
const Color &c = image->get_pixel(column_index, row_index);
|
||||||
fully_transparent = fully_transparent && (c.a == 0.f);
|
fully_transparent = fully_transparent && (c.a == 0.f);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "display_server.h"
|
#include "display_server.h"
|
||||||
|
|
||||||
#include "core/input/input.h"
|
#include "core/input/input.h"
|
||||||
#include "scene/resources/atlas_texture.h"
|
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
#include "servers/display_server_headless.h"
|
#include "servers/display_server_headless.h"
|
||||||
|
|
||||||
|
@ -1124,35 +1123,22 @@ void DisplayServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(TTS_UTTERANCE_BOUNDARY);
|
BIND_ENUM_CONSTANT(TTS_UTTERANCE_BOUNDARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image> DisplayServer::_get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot, Rect2 &r_atlas_rect) {
|
Ref<Image> DisplayServer::_get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot) {
|
||||||
Ref<Image> image;
|
Ref<Image> image;
|
||||||
ERR_FAIL_COND_V_MSG(p_hotspot.x < 0 || p_hotspot.y < 0, image, "Hotspot outside cursor image.");
|
ERR_FAIL_COND_V_MSG(p_hotspot.x < 0 || p_hotspot.y < 0, image, "Hotspot outside cursor image.");
|
||||||
|
|
||||||
Size2 texture_size;
|
|
||||||
|
|
||||||
Ref<Texture2D> texture = p_cursor;
|
Ref<Texture2D> texture = p_cursor;
|
||||||
if (texture.is_valid()) {
|
if (texture.is_valid()) {
|
||||||
Ref<AtlasTexture> atlas_texture = p_cursor;
|
|
||||||
|
|
||||||
if (atlas_texture.is_valid()) {
|
|
||||||
texture = atlas_texture->get_atlas();
|
|
||||||
r_atlas_rect.size = texture->get_size();
|
|
||||||
r_atlas_rect.position = atlas_texture->get_region().position;
|
|
||||||
texture_size = atlas_texture->get_region().size;
|
|
||||||
} else {
|
|
||||||
texture_size = texture->get_size();
|
|
||||||
}
|
|
||||||
image = texture->get_image();
|
image = texture->get_image();
|
||||||
} else {
|
} else {
|
||||||
image = p_cursor;
|
image = p_cursor;
|
||||||
ERR_FAIL_COND_V(image.is_null(), image);
|
|
||||||
texture_size = image->get_size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height, image, "Hotspot outside cursor image.");
|
|
||||||
ERR_FAIL_COND_V_MSG(texture_size.width > 256 || texture_size.height > 256, image, "Cursor image too big. Max supported size is 256x256.");
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(image.is_null(), image);
|
ERR_FAIL_COND_V(image.is_null(), image);
|
||||||
|
|
||||||
|
Size2 image_size = image->get_size();
|
||||||
|
ERR_FAIL_COND_V_MSG(p_hotspot.x > image_size.width || p_hotspot.y > image_size.height, image, "Hotspot outside cursor image.");
|
||||||
|
ERR_FAIL_COND_V_MSG(image_size.width > 256 || image_size.height > 256, image, "Cursor image too big. Max supported size is 256x256.");
|
||||||
|
|
||||||
if (image->is_compressed()) {
|
if (image->is_compressed()) {
|
||||||
image = image->duplicate(true);
|
image = image->duplicate(true);
|
||||||
Error err = image->decompress();
|
Error err = image->decompress();
|
||||||
|
|
|
@ -101,7 +101,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
static Ref<Image> _get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot, Rect2 &r_atlas_rect);
|
static Ref<Image> _get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MAX_SERVERS = 64
|
MAX_SERVERS = 64
|
||||||
|
@ -248,8 +248,8 @@ public:
|
||||||
virtual void tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable);
|
virtual void tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable);
|
||||||
virtual void tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos = 0);
|
virtual void tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos = 0);
|
||||||
|
|
||||||
virtual bool is_dark_mode_supported() const { return false; };
|
virtual bool is_dark_mode_supported() const { return false; }
|
||||||
virtual bool is_dark_mode() const { return false; };
|
virtual bool is_dark_mode() const { return false; }
|
||||||
virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }
|
virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }
|
||||||
virtual Color get_base_color() const { return Color(0, 0, 0, 0); }
|
virtual Color get_base_color() const { return Color(0, 0, 0, 0); }
|
||||||
virtual void set_system_theme_change_callback(const Callable &p_callable) {}
|
virtual void set_system_theme_change_callback(const Callable &p_callable) {}
|
||||||
|
@ -338,8 +338,8 @@ public:
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
|
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
|
||||||
virtual Color screen_get_pixel(const Point2i &p_position) const { return Color(); };
|
virtual Color screen_get_pixel(const Point2i &p_position) const { return Color(); }
|
||||||
virtual Ref<Image> screen_get_image(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return Ref<Image>(); };
|
virtual Ref<Image> screen_get_image(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return Ref<Image>(); }
|
||||||
virtual bool is_touchscreen_available() const;
|
virtual bool is_touchscreen_available() const;
|
||||||
|
|
||||||
// Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
|
// Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
|
||||||
|
@ -398,9 +398,9 @@ public:
|
||||||
virtual void show_window(WindowID p_id);
|
virtual void show_window(WindowID p_id);
|
||||||
virtual void delete_sub_window(WindowID p_id);
|
virtual void delete_sub_window(WindowID p_id);
|
||||||
|
|
||||||
virtual WindowID window_get_active_popup() const { return INVALID_WINDOW_ID; };
|
virtual WindowID window_get_active_popup() const { return INVALID_WINDOW_ID; }
|
||||||
virtual void window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect){};
|
virtual void window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) {}
|
||||||
virtual Rect2i window_get_popup_safe_rect(WindowID p_window) const { return Rect2i(); };
|
virtual Rect2i window_get_popup_safe_rect(WindowID p_window) const { return Rect2i(); }
|
||||||
|
|
||||||
virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const;
|
virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const;
|
||||||
|
|
||||||
|
@ -555,10 +555,10 @@ public:
|
||||||
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const;
|
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const;
|
||||||
virtual Key keyboard_get_label_from_physical(Key p_keycode) const;
|
virtual Key keyboard_get_label_from_physical(Key p_keycode) const;
|
||||||
|
|
||||||
virtual int tablet_get_driver_count() const { return 1; };
|
virtual int tablet_get_driver_count() const { return 1; }
|
||||||
virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
|
virtual String tablet_get_driver_name(int p_driver) const { return "default"; }
|
||||||
virtual String tablet_get_current_driver() const { return "default"; };
|
virtual String tablet_get_current_driver() const { return "default"; }
|
||||||
virtual void tablet_set_current_driver(const String &p_driver){};
|
virtual void tablet_set_current_driver(const String &p_driver) {}
|
||||||
|
|
||||||
virtual void process_events() = 0;
|
virtual void process_events() = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue