User Tag List

Results 1 to 14 of 14

Thread: [ TUTORIAL / C++ Advanced ] Custom hardware cursor loading for Win and Mac.

  1. #1
    0

    [ TUTORIAL / C++ Advanced ] Custom hardware cursor loading for Win and Mac.

    I decided to create this tutorial when I got answer from one of the UE4 devs that custom hardware cursor feature won't be added and they're working at some software implementation instead to make it possible for those who lacks special OS features knowledge.

    But for those who still want lag-free custom hardware cursor I share my code which was already tested on Win 7 and OS X 10.9. Let's go!

    But first let's define some requirements:
    • This solution is for source-based builds, because we're gonna change engine source code.
    • It's for 4.4 version. I haven't tested it in 4.3 and tested windows cursor in 4.5 preview.
    • We will use .cur and .ani types for Windows platform and .png for OS X (but you can feel free to extend functionality by using third party libs like SDL_image)
    • We'll take hotspot coordinates from cursor resource in Windows and will manually enter them in OS X.


    Ok, let's edit basic engine cursor interface and add a couple of functions there. Open file Engine/Source/Runtime/Core/Public/GenericPlatform/ICursor.h and add inside class ICursor:
    Code:
    public:
    	/* Sets image from file for cursor of certain type */
    	virtual void SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot) = 0;
    
    	/* Sets default image for cursor of certain type */
    	virtual void ResetCursor(EMouseCursor::Type CursorToReset) = 0;
    Next, let's implement these functions for both platforms. First lets edit Engine/Source/Runtime/Core/Public/Windows/WindowsCursor.h and Engine/Source/Runtime/Core/Private/Windows/WindowsCursor.cpp:

    .h
    Code:
    public:
    	virtual void SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot) override;
    
    	virtual void ResetCursor(EMouseCursor::Type CursorToReset) override;
    .cpp
    Code:
    void FWindowsCursor::SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot)
    {
    	// Check if file exists and it is .cur or .ani type.
    	if (IFileManager::Get().FileSize(*PathToCursor) == INDEX_NONE || !(PathToCursor.EndsWith(TEXT(".cur")) || PathToCursor.EndsWith(TEXT(".ani"))))
    	{
    		return;
    	}
    
    	// Loading resource from file. We ignore CursorHotSpot parameter and taking hotspot coords from resource.
    	HCURSOR CursorHandle = LoadCursorFromFile((LPCTSTR)*PathToCursor);
        CursorHandles[CursorToChange] = CursorHandle;
    }
    
    void FWindowsCursor::ResetCursor(EMouseCursor::Type CursorToReset)
    {
    	HCURSOR CursorHandle = NULL;
    	switch (CursorToReset)
    	{
    	case EMouseCursor::None:
    		// The mouse cursor will not be visible when None is used
    		break;
    
    	case EMouseCursor::Default:
    		CursorHandle = ::LoadCursor(NULL, IDC_ARROW);
    		break;
    
    	case EMouseCursor::TextEditBeam:
    		CursorHandle = ::LoadCursor(NULL, IDC_IBEAM);
    		break;
    
    	case EMouseCursor::ResizeLeftRight:
    		CursorHandle = ::LoadCursor(NULL, IDC_SIZEWE);
    		break;
    
    	case EMouseCursor::ResizeUpDown:
    		CursorHandle = ::LoadCursor(NULL, IDC_SIZENS);
    		break;
    
    	case EMouseCursor::ResizeSouthEast:
    		CursorHandle = ::LoadCursor(NULL, IDC_SIZENWSE);
    		break;
    
    	case EMouseCursor::ResizeSouthWest:
    		CursorHandle = ::LoadCursor(NULL, IDC_SIZENESW);
    		break;
    
    	case EMouseCursor::CardinalCross:
    		CursorHandle = ::LoadCursor(NULL, IDC_SIZEALL);
    		break;
    
    	case EMouseCursor::Crosshairs:
    		CursorHandle = ::LoadCursor(NULL, IDC_CROSS);
    		break;
    
    	case EMouseCursor::Hand:
    		CursorHandle = ::LoadCursor(NULL, IDC_HAND);
    		break;
    
    	case EMouseCursor::GrabHand:
    		CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString(FPlatformProcess::BaseDir()) / FString::Printf(TEXT("%sEditor/Slate/Cursor/grabhand.cur"), *FPaths::EngineContentDir())));
    		if (CursorHandle == NULL)
    		{
    			// Failed to load file, fall back
    			CursorHandle = ::LoadCursor(NULL, IDC_HAND);
    		}
    		break;
    
    	case EMouseCursor::GrabHandClosed:
    		CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString(FPlatformProcess::BaseDir()) / FString::Printf(TEXT("%sEditor/Slate/Cursor/grabhand_closed.cur"), *FPaths::EngineContentDir())));
    		if (CursorHandle == NULL)
    		{
    			// Failed to load file, fall back
    			CursorHandle = ::LoadCursor(NULL, IDC_HAND);
    		}
    		break;
    
    	case EMouseCursor::SlashedCircle:
    		CursorHandle = ::LoadCursor(NULL, IDC_NO);
    		break;
    
    	case EMouseCursor::EyeDropper:
    		CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString(FPlatformProcess::BaseDir()) / FString::Printf(TEXT("%sEditor/Slate/Icons/eyedropper.cur"), *FPaths::EngineContentDir())));
    		break;
    
    		// NOTE: For custom app cursors, use:
    		//		CursorHandle = ::LoadCursor( InstanceHandle, (LPCWSTR)MY_RESOURCE_ID );
    
    	default:
    		// Unrecognized cursor type!
    		check(0);
    		break;
    	}
    
    	if (CursorHandle != NULL)
    	{
    		CursorHandles[CursorToReset] = CursorHandle;
    	}
    }
    Ok, now it's Mac's turn. Edit Engine/Source/Runtime/Core/Public/Mac/MacCursor.h and Engine/Source/Runtime/Core/Private/Mac/MacCursor.cpp:

    .h
    Code:
    public:
    	virtual void SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot);
    
    	virtual void ResetCursor(EMouseCursor::Type CursorToReset);
    .cpp
    Code:
    void FMacCursor::SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot)
    {
        // Check if file exists and is png type
    	if (IFileManager::Get().FileSize(*PathToCursor) == INDEX_NONE || !PathToCursor.EndsWith(TEXT(".png")))
    	{
    		return;
    	}
    
    	// Loading cursor image from file
        NSImage *CursorImage = [[NSImage alloc] initWithContentsOfFile:PathToCursor.GetNSString()];
    	NSCursor *CursorHandle = [[NSCursor alloc] initWithImage:CursorImage hotSpot : NSMakePoint(CursorHotSpot.X, CursorHotSpot.Y)];
    	[CursorImage release];
    
    	CursorHandles[CursorToChange] = CursorHandle;
    }
    
    void FMacCursor::ResetCursor(EMouseCursor::Type CursorToReset)
    {
    	NSCursor *CursorHandle = NULL;
    
    	switch (CursorToReset)
    	{
    	case EMouseCursor::None:
    		break;
    
    	case EMouseCursor::Default:
    		CursorHandle = [NSCursor arrowCursor];
    		break;
    
    	case EMouseCursor::TextEditBeam:
    		CursorHandle = [NSCursor IBeamCursor];
    		break;
    
    	case EMouseCursor::ResizeLeftRight:
    		CursorHandle = [NSCursor resizeLeftRightCursor];
    		break;
    
    	case EMouseCursor::ResizeUpDown:
    		CursorHandle = [NSCursor resizeUpDownCursor];
    		break;
    
    	case EMouseCursor::ResizeSouthEast:
    	{
    		FString Path = FString::Printf(TEXT("%s%sEditor/Slate/Cursor/SouthEastCursor.png"), FPlatformProcess::BaseDir(), *FPaths::EngineContentDir());
    		NSImage* CursorImage = [[NSImage alloc] initWithContentsOfFile:Path.GetNSString()];
    		CursorHandle = [[NSCursor alloc] initWithImage:CursorImage hotSpot : NSMakePoint(8, 8)];
    		[CursorImage release];
    		break;
    	}
    
    	case EMouseCursor::ResizeSouthWest:
    	{
    		FString Path = FString::Printf(TEXT("%s%sEditor/Slate/Cursor/SouthWestCursor.png"), FPlatformProcess::BaseDir(), *FPaths::EngineContentDir());
    		NSImage* CursorImage = [[NSImage alloc] initWithContentsOfFile:Path.GetNSString()];
    		CursorHandle = [[NSCursor alloc] initWithImage:CursorImage hotSpot : NSMakePoint(8, 8)];
    		[CursorImage release];
    		break;
    	}
    
    	case EMouseCursor::CardinalCross:
    	{
    		FString Path = FString::Printf(TEXT("%s%sEditor/Slate/Cursor/CardinalCrossCursor.png"), FPlatformProcess::BaseDir(), *FPaths::EngineContentDir());
    		NSImage* CursorImage = [[NSImage alloc] initWithContentsOfFile:Path.GetNSString()];
    		CursorHandle = [[NSCursor alloc] initWithImage:CursorImage hotSpot : NSMakePoint(8, 8)];
    		[CursorImage release];
    		break;
    	}
    
    	case EMouseCursor::Crosshairs:
    		CursorHandle = [NSCursor crosshairCursor];
    		break;
    
    	case EMouseCursor::Hand:
    		CursorHandle = [NSCursor pointingHandCursor];
    		break;
    
    	case EMouseCursor::GrabHand:
    		CursorHandle = [NSCursor openHandCursor];
    		break;
    
    	case EMouseCursor::GrabHandClosed:
    		CursorHandle = [NSCursor closedHandCursor];
    		break;
    
    	case EMouseCursor::SlashedCircle:
    		CursorHandle = [NSCursor operationNotAllowedCursor];
    		break;
    
    	case EMouseCursor::EyeDropper:
    	{
    		FString Path = FString::Printf(TEXT("%s%sEditor/Slate/Cursor/EyeDropperCursor.png"), FPlatformProcess::BaseDir(), *FPaths::EngineContentDir());
    		NSImage* CursorImage = [[NSImage alloc] initWithContentsOfFile:Path.GetNSString()];
    		CursorHandle = [[NSCursor alloc] initWithImage:CursorImage hotSpot : NSMakePoint(1, 17)];
    		[CursorImage release];
    		break;
    	}
    
    	default:
    		// Unrecognized cursor type!
    		check(0);
    		break;
    	}
    
    	if (CursorHandle != NULL)
    	{
    		CursorHandles[CursorToReset] = CursorHandle;
    	}
    }
    So, those are code snippets for two platforms. Now we just need to make our Slate system use it. The best place to get reference of our Platform application with cursor class is SlateApplication class. We're gonna edit Engine/Source/Runtime/Slate/Public/Framework/Application/SlateApplication.h and Engine/Source/Runtime/Slate/Private/Framework/Application/SlateApplication.cpp:

    .h (put everything inside of class SLATE_API FSlateApplication)
    Code:
    	// Custom Cursors setup
    public:
    	/**
    	* Sets the image of the cursor.
    	*
    	* @param CursorToChange		The type of cursor to set image for.
    	* @param PathToImageFile	The path to the cursor image file.
    	* @param CursorHotSpotThe coordinates of cursor hotspot
    	*/
    	virtual void SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToImageFile, FIntPoint CursorHotSpot = FIntPoint(0,0));
    
    	/**
    	* Sets the default image of cursor.
    	*
    	* @param CursorToReset		The type of cursor to set its default image for.
    	*/
    	virtual void ResetCursor(EMouseCursor::Type CursorToReset);
    
    	// End Custom Cursor Setup
    .cpp
    Code:
    void FSlateApplication::SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToImageFile, FIntPoint CursorHotSpot)
    {
    	if (PlatformApplication->Cursor.IsValid())
    	{
    		PlatformApplication->Cursor.Get()->SetCustomCursor(CursorToChange, PathToImageFile, CursorHotSpot);
    	}
    }
    
    void FSlateApplication::ResetCursor(EMouseCursor::Type CursorToReset)
    {
    	if (PlatformApplication->Cursor.IsValid())
    	{
    		PlatformApplication->Cursor.Get()->ResetCursor(CursorToReset);
    	}
    }
    That's it! Done. Build your engine and enjoy. =)

    Here's an example of how to use it. Let's assume that we are on Windows platform and we have set of cursors in our Content/Cursors folder:

    Code:
    FString Path = FPaths::GameContentDir() / "Cursors";
    
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::Default,			Path / "Default.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::TextEditBeam,		Path / "TextEditBeam.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeLeftRight,		Path / "ResizeLeftRight.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeUpDown,		Path / "ResizeUpDown.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeSouthEast,		Path / "ResizeSouthEast.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeSouthWest,		Path / "ResizeSouthWest.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::CardinalCross,		Path / "CardinalCross.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::Crosshairs,		Path / "Crosshairs.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::Hand,			Path / "Hand.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::GrabHand,		Path / "GrabHand.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::GrabHandClosed,		Path / "GrabHandClosed.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::SlashedCircle,		Path / "SlashedCircle.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::EyeDropper,		Path / "EyeDropper.cur");


    P.S. I tried to make Linux implementation but could make it just half-working. The cursor image is loaded but its colors are blended and cursor looks weird. I don't have enough knowledge so I leave it for those who can do it.
    I included SDL_image library in Engine source and changed Engine/Source/Runtime/Core/Core.Build.cs to add it in AddThirdPartyPrivateStaticDependencies.
    Here are LinuxCursor .h and cpp snippets:

    .h
    Code:
    public:
    	virtual void SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot) override;
    
    	virtual void ResetCursor(EMouseCursor::Type CursorToReset) override;
    .cpp
    Code:
    void FLinuxCursor::SetCustomCursor(EMouseCursor::Type CursorToChange, FString PathToCursor, FIntPoint CursorHotSpot)
    {
        // Check if file exists
    	if (IFileManager::Get().FileSize(*PathToCursor) == INDEX_NONE) return;
    
    	SDL_RWops* Src = SDL_RWFromFile(TCHAR_TO_UTF8(*PathToCursor), "rb");
    
    	if (IMG_isPNG(Src))
    	{
    		SDL_Surface* CursorImage = IMG_LoadTyped_RW(Src, 1, "PNG");
    		SDL_HCursor  CursorHandle = SDL_CreateColorCursor(CursorImage, CursorHotSpot.X, CursorHotSpot.Y);
    		CursorHandles[CursorToChange] = CursorHandle;
    	}
    	else
    	{
    		SDL_FreeRW(Src);
    	}
    }
    
    void FLinuxCursor::ResetCursor(EMouseCursor::Type CursorToReset)
    {
        SDL_HCursor CursorHandle = NULL;
        
        switch( CursorToReset )
        {
    		case EMouseCursor::None:
    			// The mouse cursor will not be visible when None is used
    			break;
                
    		case EMouseCursor::Default:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_ARROW );
    			break;
                
    		case EMouseCursor::TextEditBeam:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_IBEAM );
    			break;
                
    		case EMouseCursor::ResizeLeftRight:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEWE );
    			break;
                
    		case EMouseCursor::ResizeUpDown:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENS );
    			break;
                
    		case EMouseCursor::ResizeSouthEast:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENWSE );
    			break;
                
    		case EMouseCursor::ResizeSouthWest:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENESW );
    			break;
                
    		case EMouseCursor::CardinalCross:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEALL );
    			break;
                
    		case EMouseCursor::Crosshairs:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_CROSSHAIR );
    			break;
                
    		case EMouseCursor::Hand:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_HAND );
    			break;
                
    		case EMouseCursor::GrabHand:
    			//CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString( FPlatformProcess::BaseDir() ) / FString::Printf( TEXT("%sEditor/Slate/Old/grabhand.cur"), *FPaths::EngineContentDir() )));
    			//if (CursorHandle == NULL)
    			//{
    			//	// Failed to load file, fall back
                CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_HAND );
    			//}
    			break;
                
    		case EMouseCursor::GrabHandClosed:
    			//CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString( FPlatformProcess::BaseDir() ) / FString::Printf( TEXT("%sEditor/Slate/Old/grabhand_closed.cur"), *FPaths::EngineContentDir() )));
    			//if (CursorHandle == NULL)
    			//{
    			//	// Failed to load file, fall back
                CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_HAND );
    			//}
    			break;
                
    		case EMouseCursor::SlashedCircle:
    			CursorHandle = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NO );
    			break;
                
    		case EMouseCursor::EyeDropper:
    			//CursorHandle = LoadCursorFromFile((LPCTSTR)*(FString( FPlatformProcess::BaseDir() ) / FString::Printf( TEXT("%sEditor/Slate/Icons/eyedropper.cur"), *FPaths::EngineContentDir() )));
    			break;
                
    			// NOTE: For custom app cursors, use:
    			//		CursorHandle = ::LoadCursor( InstanceHandle, (LPCWSTR)MY_RESOURCE_ID );
                
    		default:
    			// Unrecognized cursor type!
    			check( 0 );
    			break;
        }
        
        if(CursorHandle != NULL)
        {
            CursorHandles[CursorToReset] = CursorHandle;
        }
    }

  2. #2
    0
    Nice work, this seems really useful for getting that extra level of polish in games that use a cursor.

  3. #3
    0
    Thanks a lot for sharing! Very cool.
    Lead Gameplay Developer at Space Dust Studios/Varkian Empire (@butterparty)
    Obliteracers: Thread // Blog // @obliteracers // Facebook // Reddit // Steam

  4. #4
    0
    Update: Just tried this out under Windows 8.1 64-bit and it worked exactly as advertised. Thanks again!
    Lead Gameplay Developer at Space Dust Studios/Varkian Empire (@butterparty)
    Obliteracers: Thread // Blog // @obliteracers // Facebook // Reddit // Steam

  5. #5
    0
    Yes, I can also add that this works on versions up to 4.6.1 as intended. Thanks to Epic who doesn't play with this part of code making this solution stable.
    Tim S.
    Familio Games

  6. #6
    0
    I added the mentioned code and rebuilt the engine. I don't know what to do with the last part:
    FString Path = FPaths::GameContentDir() / "Cursors";

    FSlateApplication::Get().SetCustomCursor(EMouseCursor:efault, Path / "Default.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::TextEditBeam, Path / "TextEditBeam.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeLeftRight, Path / "ResizeLeftRight.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeUpDown, Path / "ResizeUpDown.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeSouthEast, Path / "ResizeSouthEast.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::ResizeSouthWest, Path / "ResizeSouthWest.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::CardinalCross, Path / "CardinalCross.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::Crosshairs, Path / "Crosshairs.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::Hand, Path / "Hand.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::GrabHand, Path / "GrabHand.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::GrabHandClosed, Path / "GrabHandClosed.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::SlashedCircle, Path / "SlashedCircle.cur");
    FSlateApplication::Get().SetCustomCursor(EMouseCursor::EyeDropper, Path / "EyeDropper.cur");
    Where to put this?
    And where do I put my .cur files? In the engine/content/cursors or in my project folder/content/cursors ?

  7. #7
    0
    Quote Originally Posted by SethPDA View Post
    Where to put this?
    And where do I put my .cur files? In the engine/content/cursors or in my project folder/content/cursors ?
    You put this anywhere inside your code where you want your cursors to be set. It could be some init function or player choosing a faction procedure and his GUI changes according to that or anywhere else.

    FPaths::GameContentDir() return a path to your cooked Content folder so in my example you should put cur files in Content/Cursor folder and include that folder in project build settings to be copied to cooked content folder.
    Or you can use any other path of your file system. If you can get your game install folder other way you can use that.
    Tim S.
    Familio Games

  8. #8
    0
    If I put this in my HUD-Class, I am getting "use of undefined type 'FSlateApplication'

  9. #9
    0
    Quote Originally Posted by Braindrain85 View Post
    If I put this in my HUD-Class, I am getting "use of undefined type 'FSlateApplication'
    Did you set up Slate correctly?
    You need to add
    PHP Code:
    PublicDependencyModuleNames.AddRange(new string[] { "Slate""SlateCore" }); 
    to your project's Build.cs file. And also you need to include SlateBasics.h in your source file.
    I purposely omitted that in example assuming Slate is already set up.
    Tim S.
    Familio Games

  10. #10
    0
    Thanks Tim! That works now.

    I actually tried another thing to re-enabling mouse-look after disabling the cursor (without having to click) writing the following lines:

    auto CurrentFocus = FSlateApplication::Get().GetKeyboardFocusedWidget();
    FSlateApplication::Get().ClearKeyboardFocus(EKeyboardFocusCause::SetDirectly);
    FSlateApplication::Get().SetKeyboardFocus(CurrentFocus);
    That didn't work for me. But I think this is getting OT.

    EDIT: Nevermind, it works... :-)
    Last edited by Braindrain85; 02-12-2015 at 05:22 PM.

  11. #11
    0
    Supporter
    Join Date
    Jun 2015
    Posts
    2
    Just wanted to confirm that this still works with the most recent dev source build. Thanks a bunch!

  12. #12
    0
    This is awsome@! yes, awsome!
    Thanks for sharing.

  13. #13
    0
    Supporter
    Join Date
    Jun 2015
    Posts
    2
    For the people that have implemented this, I am curious if you are having a similar issue. If the mouse state changes and the mouse does not change position, it doesn't update. For instance, in our game, if a unit moves under the mouse, the call to change the cursor fires and but the actual image updating isn't done until the mouse moves at least 1 pixel. I have more time to look into it today so I will figure out exactly what is going wrong and post back here. In the meantime however, if anyone has come across a similar problem and knows how to fix it, please share.

  14. #14
    0
    Sorry for being absent. Email notifications stopped coming. Don't know why.

    For cursor not redrawn fix you could use pseudo movement for mouse cursor by using: FSlateApplication::Get()->SetCursorPos(MouseCoordinates), where MouseCoordinates is current mouse coordinates you get by GetMousePosition(). This should force cursor redraw.
    I can't check if that works now because currently I don't have a working copy of UE build. But if my memory serves me right I fixed that cursor behaviour by using method I've just explained.
    Tim S.
    Familio Games

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •