summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorGuilherme Felipe <guilhermefelipecgs@gmail.com>2018-05-08 14:07:43 +0000
committerGuilherme Felipe <guilhermefelipecgs@gmail.com>2018-05-09 12:44:43 +0000
commit8ead09342d44fb39b28b400cb2fcb3c947f8f34f (patch)
tree1915a94b1ddd5f4ac85ade1405c75f24c3c76fb5 /platform
parente668757aa9ff4ccd3a90b1f402aba8a424b4c11d (diff)
Add support for atlas texture on set_custom_mouse_cursor
Diffstat (limited to 'platform')
-rw-r--r--platform/osx/os_osx.mm61
-rw-r--r--platform/windows/os_windows.cpp44
-rw-r--r--platform/x11/os_x11.cpp42
3 files changed, 123 insertions, 24 deletions
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index eaf89f7d0f..80d466f4b6 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1513,39 +1513,78 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
Ref<Texture> texture = p_cursor;
- Ref<Image> image = texture->get_data();
+ Ref<AtlasTexture> atlas_texture = p_cursor;
+ Ref<Image> image;
+ Size2 texture_size;
+ Rect2 atlas_rect;
- ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256);
+ if (texture.is_valid()) {
+ image = texture->get_data();
+ }
+
+ if (!image.is_valid() && atlas_texture.is_valid()) {
+ texture = atlas_texture->get_atlas();
+
+ atlas_rect.size.width = texture->get_width();
+ atlas_rect.size.height = texture->get_height();
+ atlas_rect.position.x = atlas_texture->get_region().position.x;
+ atlas_rect.position.y = atlas_texture->get_region().position.y;
+
+ texture_size.width = atlas_texture->get_region().size.x;
+ texture_size.height = atlas_texture->get_region().size.y;
+ } else if (image.is_valid()) {
+ texture_size.width = texture->get_width();
+ texture_size.height = texture->get_height();
+ }
+
+ ERR_FAIL_COND(!texture.is_valid());
+ ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
+
+ image = texture->get_data();
NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
- pixelsWide:image->get_width()
- pixelsHigh:image->get_height()
+ pixelsWide:int(texture_size.width)
+ pixelsHigh:int(texture_size.height)
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
- bytesPerRow:image->get_width() * 4
+ bytesPerRow:int(texture_size.width) * 4
bitsPerPixel:32] autorelease];
ERR_FAIL_COND(imgrep == nil);
uint8_t *pixels = [imgrep bitmapData];
- int len = image->get_width() * image->get_height();
+ int len = int(texture_size.width * texture_size.height);
PoolVector<uint8_t> data = image->get_data();
PoolVector<uint8_t>::Read r = data.read();
+ image->lock();
+
/* Premultiply the alpha channel */
for (int i = 0; i < len; i++) {
- uint8_t alpha = r[i * 4 + 3];
- pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255);
- pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255);
- pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255);
+ int row_index = floor(i / texture_size.width) + atlas_rect.position.y;
+ int column_index = (i % int(texture_size.width)) + atlas_rect.position.x;
+
+ if (atlas_texture.is_valid()) {
+ 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();
+
+ uint8_t alpha = (color >> 24) & 0xFF;
+ pixels[i * 4 + 0] = ((color >> 16) & 0xFF) * alpha / 255;
+ pixels[i * 4 + 1] = ((color >> 8) & 0xFF) * alpha / 255;
+ pixels[i * 4 + 2] = ((color)&0xFF) * alpha / 255;
pixels[i * 4 + 3] = alpha;
}
- NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(image->get_width(), image->get_height())] autorelease];
+ image->unlock();
+
+ NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(texture_size.width, texture_size.height)] autorelease];
[nsimage addRepresentation:imgrep];
NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)];
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 54a5d91eb4..2850d38ce4 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -2033,27 +2033,57 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
Ref<Texture> texture = p_cursor;
- Ref<Image> image = texture->get_data();
+ Ref<AtlasTexture> atlas_texture = p_cursor;
+ Ref<Image> image;
+ Size2 texture_size;
+ Rect2 atlas_rect;
- UINT image_size = texture->get_width() * texture->get_height();
- UINT size = sizeof(UINT) * image_size;
+ if (texture.is_valid()) {
+ image = texture->get_data();
+ }
+
+ if (!image.is_valid() && atlas_texture.is_valid()) {
+ texture = atlas_texture->get_atlas();
+
+ atlas_rect.size.width = texture->get_width();
+ atlas_rect.size.height = texture->get_height();
+ atlas_rect.position.x = atlas_texture->get_region().position.x;
+ atlas_rect.position.y = atlas_texture->get_region().position.y;
+
+ texture_size.width = atlas_texture->get_region().size.x;
+ texture_size.height = atlas_texture->get_region().size.y;
+ } else if (image.is_valid()) {
+ texture_size.width = texture->get_width();
+ texture_size.height = texture->get_height();
+ }
- ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256);
+ ERR_FAIL_COND(!texture.is_valid());
+ ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
+
+ image = texture->get_data();
+
+ UINT image_size = texture_size.width * texture_size.height;
+ UINT size = sizeof(UINT) * image_size;
// Create the BITMAP with alpha channel
COLORREF *buffer = (COLORREF *)malloc(sizeof(COLORREF) * image_size);
image->lock();
for (UINT index = 0; index < image_size; index++) {
- int row_index = floor(index / texture->get_width());
- int column_index = index % texture->get_width();
+ int row_index = floor(index / texture_size.width) + atlas_rect.position.y;
+ int column_index = (index % int(texture_size.width)) + atlas_rect.position.x;
+
+ if (atlas_texture.is_valid()) {
+ column_index = MIN(column_index, atlas_rect.size.width - 1);
+ row_index = MIN(row_index, atlas_rect.size.height - 1);
+ }
*(buffer + index) = image->get_pixel(column_index, row_index).to_argb32();
}
image->unlock();
// Using 4 channels, so 4 * 8 bits
- HBITMAP bitmap = CreateBitmap(texture->get_width(), texture->get_height(), 1, 4 * 8, buffer);
+ HBITMAP bitmap = CreateBitmap(texture_size.width, texture_size.height, 1, 4 * 8, buffer);
COLORREF clrTransparent = -1;
// Create the AND and XOR masks for the bitmap
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index d1b87dac6f..117995ea48 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2420,13 +2420,38 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) {
void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
Ref<Texture> texture = p_cursor;
- Ref<Image> image = texture->get_data();
+ Ref<AtlasTexture> atlas_texture = p_cursor;
+ Ref<Image> image;
+ Size2 texture_size;
+ Rect2 atlas_rect;
- ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256);
+ if (texture.is_valid()) {
+ image = texture->get_data();
+ }
+
+ if (!image.is_valid() && atlas_texture.is_valid()) {
+ texture = atlas_texture->get_atlas();
+
+ atlas_rect.size.width = texture->get_width();
+ atlas_rect.size.height = texture->get_height();
+ atlas_rect.position.x = atlas_texture->get_region().position.x;
+ atlas_rect.position.y = atlas_texture->get_region().position.y;
+
+ texture_size.width = atlas_texture->get_region().size.x;
+ texture_size.height = atlas_texture->get_region().size.y;
+ } else if (image.is_valid()) {
+ texture_size.width = texture->get_width();
+ texture_size.height = texture->get_height();
+ }
+
+ ERR_FAIL_COND(!texture.is_valid());
+ ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
+
+ image = texture->get_data();
// Create the cursor structure
- XcursorImage *cursor_image = XcursorImageCreate(texture->get_width(), texture->get_height());
- XcursorUInt image_size = texture->get_width() * texture->get_height();
+ XcursorImage *cursor_image = XcursorImageCreate(texture_size.width, texture_size.height);
+ XcursorUInt image_size = texture_size.width * texture_size.height;
XcursorDim size = sizeof(XcursorPixel) * image_size;
cursor_image->version = 1;
@@ -2440,8 +2465,13 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
image->lock();
for (XcursorPixel index = 0; index < image_size; index++) {
- int row_index = floor(index / texture->get_width());
- int column_index = index % texture->get_width();
+ int row_index = floor(index / texture_size.width) + atlas_rect.position.y;
+ int column_index = (index % int(texture_size.width)) + atlas_rect.position.x;
+
+ if (atlas_texture.is_valid()) {
+ 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();
}