MouseDown drag problem (bug?)

There seems to be an problem with the way playerController->IsInputKeyDown(EKeys::LeftMouseButton), it is causing issues with getting updated screen coordinates of my mouse cursor.

I am currently using the mouse to orbit a camera around, this all works perfectly when no mouse buttons are being pressed, but if I press and hold any mouse button while, the playerController->GetMousePosition(x, y); is not updating nearly as frequently, which causes skipping in my camera orbiting.

This seems to be a bug with how single-clicks are being handled by the engine, because when I double-click and hold the button down and drag around it works as normal.

Other things to note are that this problem seems to only show up in the standalone player or on packaged builds, it is acting fine within the editor viewports. Also, limiting my CPU affinity to 1 core allows me to receive more updates, so maybe this is an issue with threading?

Below is the basic code in our CamerPawn class …

void ACameraPawn::CheckForRotateCamera()
{    
	if (playerController->IsInputKeyDown(EKeys::LeftMouseButton))
	{    
		if (isDragging)
		{
			playerController->InputYawScale = 400.0f;
			playerController->InputPitchScale = -400.0f;

			int32 screenX;
			int32 screenY;
			playerController->GetViewportSize(screenX, screenY);
			FVector2D screenSize = FVector2D(screenX, screenY);

			float x, y;
			playerController->GetMousePosition(x, y);

			float xDelta = x - lastX;
			float yDelta = y - lastY;

			lastX = x;
			lastY = y;

			//Add movement to the controller
			AddControllerYawInput(xDelta / screenSize.X);
			AddControllerPitchInput(yDelta / screenSize.Y);
		}
		else
		{
			isDragging = true;
			playerController->GetMousePosition(lastX, lastY);
		}
	}
	else
	{
		isDragging = false;
	}
}

Any help is greatly appreciated, thanks!

Hey blurdot-

The code shown seems to control the camera only when the mouse button is being held. Is the code that controls the camera without the button being held the same or similar to what is shown above?

Thanks

For testing purposes I just changed the MouseDown check to this:

if (true || playerController->IsInputKeyDown(EKeys::LeftMouseButton))

Which will show that the camera orbits smoothly until any mouse button is held down.

I created a project to test the call playerController->IsInputKeyDown(EKeys::LeftMouseButton) which I called on tick (I assume you’re using tick to constantly update the camera). As long as I held the button it continued to call the code.

I’m not sure if it could be the cause but the extra calls to get the pitch/yaw scale as well as the viewport and screen size would probably not be necessary if these numbers don’t change. It might help to move them to another function (possibly BeginPlay) and then pass them into CheckForRotateCamera() as needed.

I may have to send an example build so you can see the issue. The code is being called, just less frequently with higher power computers when a mouse button is being held down. I will get a build together that can showcase the issue, is there a place to send it?

If you have a dropbox that you can upload it to you can send me the link to it as a private message on the forums.

I have exactly (more or less the same problem) how would I go to fix it.
Some of my findings:

When the frame is Bounded by GPU (no framerate limit) this is not happens -
however when the CPU takes the most time per frame this happens - how would I fix it please?

I found the very same issue here…
And because I wasn’t able to find a viable Solution over the web search I decided to post my WorkAroud
it is not the most neat/Perfect solution - however it does the Job for me.

This solution will work only for Windows and Mac (I don’t have any other platforms to make more).

PlayerController.h

#if PLATFORM_WINDOWS
#include "Windows/WindowsSystemIncludes.h"

#include "AllowWindowsPlatformTypes.h"
#include <Windows.h>
#include "HideWindowsPlatformTypes.h"
#endif //Windows

   #if PLATFORM_MAC
private:
#import <Cocoa/Cocoa.h>    
    NSWindow * m_windowHandle;
#endif

#if PLATFORM_WINDOWS
private:
	HWND m_windowHandle;
#endif

PlayerController.cpp

void APlayerController::BeginPlay()
{
    Super::BeginPlay();
//    bShowMouseCursor = true;   
    #if PLATFORM_MAC
        NSArray * windows = [[NSApplication sharedApplication] windows];
        m_windowHandle = windows[0];
    #endif

	#if PLATFORM_WINDOWS
		m_windowHandle = GetActiveWindow();
	#endif
 //...
 //...
 //...
}


void APlayerController::Tick( float DeltaSeconds )
{
    Super::Tick(DeltaSeconds);
    
    //Get ViewPortSize
    // (0,0) is at top left
    int32 viewportX, viewportY;
    GetViewportSize(viewportX, viewportY);
    
    float mouseX = 100, mouseY = 100;
    
    //If Window in focus
    bool windowInFocus = true;
    bool mouseInsideWindow = true;
    
	//Mouse warp for Mac
    #if PLATFORM_MAC
        windowInFocus = (bool)m_windowHandle.isKeyWindow;
        if(windowInFocus)
        {
            //If Window is in focus -> we must ensure the MouseWarp
            NSPoint mouse = [NSEvent mouseLocation];
            bool bx = false ,by = false;
            //If - Mouse is inside the Window we don't care!
            if(!CGRectContainsPoint((CGRect)m_windowHandle.frame, (CGPoint)mouse))
            {
                mouseInsideWindow = false;
                //WarpX
                if (mouse.x < m_windowHandle.frame.origin.x)
                {
                    mouseX = 0;
                    bx = true;
                }
                else if(mouse.x > m_windowHandle.frame.origin.x + m_windowHandle.frame.size.width)
                {
                    mouseX = viewportX;
                    bx = true;
                }
                
                //WarpY //Y has opposite coordinates in unreal
                if (mouse.y < m_windowHandle.frame.origin.y)
                {
                    mouseY = viewportY;
                    by = true;
                }
                else if(mouse.y >= m_windowHandle.frame.origin.y + m_windowHandle.frame.size.height)
                {
                    mouseY = 0;
                    by = true;
                }
                
                float temp;
                if(bx && !by)
                {
                    //get y
                    GetMousePosition(temp, mouseY);
                }
                else if (by && !bx)
                {
                    //get x
                    GetMousePosition(mouseX, temp);
                }
            }
        }
        else
        {
            //macOS Escape
            return;
        }
    #endif
    
//Do mouse warp for Windows ://
#if PLATFORM_WINDOWS
		POINT p;
		if (!GetCursorPos(&p))
		{
			//cursor position now in p.x and p.y
			return;
		}

		if (!ScreenToClient(m_windowHandle, &p))
		{
			//p.x and p.y are now relative to hwnd's client area
			return;
		}

		mouseX = (float)p.x;
		mouseY = (float)p.y;
#endif

		//if play in editor get the mouse as is.
		if (GetWorld()->WorldType == EWorldType::PIE)
		{
			GetMousePosition(mouseX, mouseY);
		}

           //At This Point The Mouse Coordinates will be stored in mouseX, mouseY float variables.

//...
//...
//...
}

Hey -

Could you create a new post for your specific issue. This will help prevent the details of your issue from being lost in this post. Please describe exactly what the behavior is that you’re seeing as well as the setup that you’re using on your end? Please provide as much detail about your issue as possible to help us investigate.

Hey ,

Sure Working on it now.
However I already posted an answer to myself here :-/

Roma.

Hi

Here is my Question Link

Thanks,

Roma.