|
@@ -1844,10 +1844,125 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
|
|
|
IDC_HELP
|
|
|
};
|
|
|
|
|
|
- SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
|
|
|
+ if (cursors[p_shape] != NULL) {
|
|
|
+ SetCursor(cursors[p_shape]);
|
|
|
+ } else {
|
|
|
+ SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
|
|
|
+ }
|
|
|
cursor_shape = 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();
|
|
|
+
|
|
|
+ UINT image_size = 32 * 32;
|
|
|
+ UINT size = sizeof(UINT) * image_size;
|
|
|
+
|
|
|
+ ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
|
|
|
+
|
|
|
+ // 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 column_index = floor(index / 32);
|
|
|
+ int row_index = index % 32;
|
|
|
+
|
|
|
+ Color pcColor = image->get_pixel(row_index, column_index);
|
|
|
+ *(buffer + index) = image->get_pixel(row_index, column_index).to_argb32();
|
|
|
+ }
|
|
|
+ image->unlock();
|
|
|
+
|
|
|
+ // Using 4 channels, so 4 * 8 bits
|
|
|
+ HBITMAP bitmap = CreateBitmap(32, 32, 1, 4 * 8, buffer);
|
|
|
+ COLORREF clrTransparent = -1;
|
|
|
+
|
|
|
+ // Create the AND and XOR masks for the bitmap
|
|
|
+ HBITMAP hAndMask = NULL;
|
|
|
+ HBITMAP hXorMask = NULL;
|
|
|
+
|
|
|
+ GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask);
|
|
|
+
|
|
|
+ if (NULL == hAndMask || NULL == hXorMask) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Finally, create the icon
|
|
|
+ ICONINFO iconinfo = { 0 };
|
|
|
+ iconinfo.fIcon = FALSE;
|
|
|
+ iconinfo.xHotspot = p_hotspot.x;
|
|
|
+ iconinfo.yHotspot = p_hotspot.y;
|
|
|
+ iconinfo.hbmMask = hAndMask;
|
|
|
+ iconinfo.hbmColor = hXorMask;
|
|
|
+
|
|
|
+ cursors[p_shape] = CreateIconIndirect(&iconinfo);
|
|
|
+
|
|
|
+ if (p_shape == CURSOR_ARROW) {
|
|
|
+ SetCursor(cursors[p_shape]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hAndMask != NULL) {
|
|
|
+ DeleteObject(hAndMask);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hXorMask != NULL) {
|
|
|
+ DeleteObject(hXorMask);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) {
|
|
|
+
|
|
|
+ // Get the system display DC
|
|
|
+ HDC hDC = GetDC(NULL);
|
|
|
+
|
|
|
+ // Create helper DC
|
|
|
+ HDC hMainDC = CreateCompatibleDC(hDC);
|
|
|
+ HDC hAndMaskDC = CreateCompatibleDC(hDC);
|
|
|
+ HDC hXorMaskDC = CreateCompatibleDC(hDC);
|
|
|
+
|
|
|
+ // Get the dimensions of the source bitmap
|
|
|
+ BITMAP bm;
|
|
|
+ GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
|
|
|
+
|
|
|
+ // Create the mask bitmaps
|
|
|
+ hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
|
|
|
+ hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
|
|
|
+
|
|
|
+ // Release the system display DC
|
|
|
+ ReleaseDC(NULL, hDC);
|
|
|
+
|
|
|
+ // Select the bitmaps to helper DC
|
|
|
+ HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap);
|
|
|
+ HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
|
|
|
+ HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
|
|
|
+
|
|
|
+ // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap
|
|
|
+ // with 'clrTransparent' will be white pixels of the monochrome bitmap
|
|
|
+ SetBkColor(hMainDC, clrTransparent);
|
|
|
+ BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY);
|
|
|
+
|
|
|
+ // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap
|
|
|
+ // with 'clrTransparent' will be black and rest the pixels same as corresponding
|
|
|
+ // pixels of the source bitmap
|
|
|
+ SetBkColor(hXorMaskDC, RGB(0, 0, 0));
|
|
|
+ SetTextColor(hXorMaskDC, RGB(255, 255, 255));
|
|
|
+ BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY);
|
|
|
+ BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND);
|
|
|
+
|
|
|
+ // Deselect bitmaps from the helper DC
|
|
|
+ SelectObject(hMainDC, hOldMainBitmap);
|
|
|
+ SelectObject(hAndMaskDC, hOldAndMaskBitmap);
|
|
|
+ SelectObject(hXorMaskDC, hOldXorMaskBitmap);
|
|
|
+
|
|
|
+ // Delete the helper DC
|
|
|
+ DeleteDC(hXorMaskDC);
|
|
|
+ DeleteDC(hAndMaskDC);
|
|
|
+ DeleteDC(hMainDC);
|
|
|
+}
|
|
|
+
|
|
|
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
|
|
|
|
|
|
if (p_blocking && r_pipe) {
|