Announcement

Collapse
No announcement yet.

Drawing a slate widget at mouse Location

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Drawing a slate widget at mouse Location

    Hello every one... I want to replace my mouse cursor with a slate widget.

    When I am using SCanvas, the location of the slate widget is appearing a lot off. Anyway how to do it?
    Code:
        IconLocation.Bind(this, &SCursorItemWidget::GetCursorLocation);
    
        ChildSlot
        [
        SNew(SCanvas)
        .Visibility(EVisibility::HitTestInvisible)
        + SCanvas::Slot()
        .Position(IconLocation)
        .Size(FVector2D(64,64))
        .HAlign(HAlign_Center)
        .VAlign(VAlign_Center)
        [
        ]
        ];
    I am getting the mouse position with something like this

    Code:
        GameHUD->PC->GetMousePosition(MouseLoc.X, MouseLoc.Y);

    But the mouse position is a lot off.. Something similar to half of what it should be.

    Click image for larger version

Name:	bandicam 2015-01-12 13-23-17-730.jpg
Views:	1
Size:	122.4 KB
ID:	1142885
    Image of what is wrong with .Position of canvas.

    I am getting another problem. When I draw the mouse like this, any slate widget present below this is not responding to mouse clicks.


    ---------- Answers Till Now ----------

    Code:
    		SAssignNew(CursorItemUI, SCursorItemWidget)
    			.InvStorage((StoragePtr));
    
    		GEngine->GameViewport->AddViewportWidgetContent(
    			SNew(SWeakWidget).PossiblyNullContent(CursorItemUI.ToSharedRef())
    			);	
    
    		CursorItemUI.Get()->SetVisibility(EVisibility::HitTestInvisible);
    This solves the 2nd problem the 2nd Widget is still above and causes no click problems.

    According to my answer Hub post,
    Something like this should work
    Code:
    FSlateApplication::Get().GetCursorPos()
    But sadly is not working

    Last edited by envenger; 01-12-2015, 06:53 AM.

    #2
    Cursor position is in absolute coordinates but SCanvas slots expect a position in relative coordinates. This is further compounded by the fact that the entire UI has a scaling factor applied depending on your resolution, so you have not only a translation offset but also a scaling offset.

    Converting between the two is most easily done through FGeometry, using AbsoluteToLocal / LocalToAbsolute. In order for AbsoluteToLocal to mean anything to the canvas, though, it has to be the canvas's geometry. Here's an excerpt of how I'm doing it in our inventory:

    Code:
    FReply FInventoryPresenter::OnInventoryMouseMove( const FGeometry& InventoryGeometry, const FPointerEvent& MouseEvent )
    {
    	FVector2D InventoryMovePos = InventoryGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() );
    
    	if( IsDraggingItem() )
    	{
    		InventoryWidget->UpdateItemDragPos( InventoryMovePos );
    
    		return FReply::Handled();
    	}
    	
    	return FReply::Unhandled();
    }
    My custom inventory SCompoundWidget exposes a delegate for OnMouseMove and my presenter registers for that. The SCanvas used for the drag and drop position is a child of that inventory widget and has the exact same geometry (no scaling, no padding, aligns set to fill), so that AbsoluteToLocal can return the proper coordinates. Then UpdateItemDragPos simply gets the Canvas slot for the drag indicator and manually updates its offsets.

    If you can't have the canvas take up the exact same geometry as a parent widget, you could also subclass SCanvas to override OnMouseMove and handle your positioning logic there.

    -Camille

    Comment


      #3
      -----------Edit------------

      Well it worked thanks...

      Can you show how did you expose a delegate to OnMouse move and register it?

      I have not never used any delegates yet.
      Last edited by envenger; 01-13-2015, 08:49 AM.

      Comment


        #4
        Originally posted by envenger View Post
        -----------Edit------------

        Well it worked thanks...

        Can you show how did you expose a delegate to OnMouse move and register it?

        I have not never used any delegates yet.
        SWidget only provides function overrides for input events, not delegates, so I simply inspired myself from SBorder's pointer event delegates. It has a both a OnMouseMove Slate event and a setter for it. Then, to register for that event, either use Slate syntax or a setter:

        Code:
        // Slate syntax
        SNew( SInventoryWidget )
        .OnMouseMove( this, &FInventoryPresenter::OnInventoryMouseMove )
        
        // Setter
        Widget->SetOnMouseMove( FPointerEventHandler::CreateSP( this, &FInventoryPresenter::OnInventoryMouseMove ) );
        I use the setter in my case because I only register for MouseMove when a drag operation is in progress.

        Comment

        Working...
        X