Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Hardware Cursor Support

Discussion in 'Scripting' started by Games-Foundry, May 19, 2011.

  1. Games-Foundry

    Games-Foundry

    Joined:
    May 19, 2011
    Posts:
    632
    Well, I've passed 100 hours of evaluating Unity3D Pro. Many headaches like no included A*Pathfinding and an inability to make Terrain rotations. I've got over those hurdles.

    Now I'm trying to implement a custom hardware cursor. I'm working on an RTS game, where the state of the cursor is used to communicate quite a lot of visual clues to the player. Using a software cursor is NOT ACCEPTABLE, any lag with the cursor will kill the gaming experience, as documented elsewhere on this forum.

    So far my exhaustive searches have lead to:
    http://forum.unity3d.com/threads/70163-Hardware-Cursor-Plugin/page2?highlight=custom+cursor
    http://msdn.microsoft.com/en-us/library/ms648045(v=vs.85).aspx
    http://blog.naver.com/PostView.nhn?blogId=sdragoon&logNo=150096564973

    and I've finally come up with the following script based on the three Windows-only solutions I can find through Google. When I run the game (within the Editor), the custom mouse pointer appears, but then vanishes when the 3D scene appears, resetting to the default windows cursor. I read somewhere that the solution only worked on .exe builds, so I ran a build and the cursor doesn't show at all in that. (Windows 7 64-bit).

    Is there anyone that has a solution they wouldn't mind sharing?

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using System.Collections;
    5. using System.Runtime.InteropServices;
    6.  
    7. public class CursorManager : MonoBehaviour
    8. {
    9.     [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
    10.     public static extern IntPtr SetCursor(IntPtr hCursor);
    11.    
    12.     [DllImport("user32.dll")]
    13.     public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
    14.    
    15.     [DllImport("user32.dll")]
    16.     public static extern IntPtr LoadImage(IntPtr hInstance, string lpImageName, uint uType, int cxDesired, int cyDesired, uint fuLoad);
    17.  
    18.     //fuLoad
    19.     public const uint LR_CREATEDIBSECTION     =0x00002000;
    20.     public const uint LR_DEFAULTCOLOR     =0x00000000;
    21.     public const uint LR_DEFAULTSIZE     =0x00000040;
    22.     public const uint LR_LOADFROMFILE     =0x00000010;
    23.     public const uint LR_LOADMAP3DCOLORS     =0x00001000;
    24.     public const uint LR_LOADTRANSPARENT     =0x00000020;
    25.     public const uint LR_MONOCHROME     =0x00000001;
    26.     public const uint LR_SHARED     =0x00008000;
    27.     public const uint LR_VGACOLOR     =0x00000080;
    28.    
    29.     public void ChangeCursorToArrow()
    30.     {
    31.         SetCursor(LoadCursor(IntPtr.Zero, 32512));
    32.     }
    33.    
    34.     public void ChangeCursorToCustom(string filePath)
    35.     {
    36.         SetCursor(LoadImage(IntPtr.Zero, filePath, 2, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE));
    37.     }
    38.    
    39.     public void Init()
    40.     {
    41.         string cursorPath = Application.dataPath+"/Resources/Cursors/normal.cur";
    42.         ChangeCursorToCustom(cursorPath);
    43.     }
    44. }
    45.  
     
    Last edited: May 19, 2011
  2. Games-Foundry

    Games-Foundry

    Joined:
    May 19, 2011
    Posts:
    632
    Well, looks like it's the Unity GUI system that is resetting the cursor.

    Anyhows, I've managed to get lubo3d's solution working for now, as I have no C++ experience.

    Please Unity Team, sort this out in the main API ASAP so it also works when playing in the Editor. I nearly threw in the towel during my eval because of this.
     
  3. MattijsKneppers

    MattijsKneppers

    Joined:
    Jun 30, 2014
    Posts:
    15
    When searching for a way to load another standard cursor already included n the OS, I ended up with this:

    Code (CSharp):
    1.  
    2.       public enum WindowsCursor
    3.         {
    4.             StandardArrowAndSmallHourglass = 32650,
    5.             StandardArrow = 32512,
    6.             Crosshair = 32515,
    7.             Hand = 32649,
    8.             ArrowAndQuestionMark = 32651,
    9.             IBeam = 32513,
    10.             //Icon = 32641, // Obsolete for applications marked version 4.0 or later.
    11.             SlashedCircle = 32648,
    12.             //Size = 32640,  // Obsolete for applications marked version 4.0 or later. Use FourPointedArrowPointingNorthSouthEastAndWest
    13.             FourPointedArrowPointingNorthSouthEastAndWest = 32646,
    14.             DoublePointedArrowPointingNortheastAndSouthwest = 32643,
    15.             DoublePointedArrowPointingNorthAndSouth = 32645,
    16.             DoublePointedArrowPointingNorthwestAndSoutheast = 32642,
    17.             DoublePointedArrowPointingWestAndEast = 32644,
    18.             VerticalArrow = 32516,
    19.             Hourglass = 32514
    20.         }
    21.    
    22.         private static void ChangeCursor(WindowsCursor cursor){
    23.             SetCursor(LoadCursor(IntPtr.Zero , (int)cursor));
    24.         }
    25.    
    26.         [DllImport("user32.dll", EntryPoint = "SetCursor")]
    27.         public static extern IntPtr SetCursor(IntPtr hCursor);
    28.    
    29.         [DllImport("user32.dll", EntryPoint = "LoadCursor")]
    30.         public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
    31.