Archive 19/01/2023.

Changing cursors

Taqer

Hi, I have a problems with switching multiple cursors in game.

When I change cursor, it flickers for a moment with default OS cursor, it’s a small thing but I want to remove it.

I have 6 cursors graphics, defined in style .xml file, and a method to change cursors:

void GameMode::ChangeCursor(GameCursorType type)
{
	if (currentCursorType == type) return;
	currentCursorType = type;

	//this will crash \/ \/ \/
	//UI* ui = GetSubsystem<UI>();
	//Cursor * cursor = ui->GetCursor();
	//cursor->SetShape(cursorNames[type]);
	//ui->SetCursor(cursor);

	//this will flicker cursor \/ \/ \/
	UI* ui = GetSubsystem<UI>();
	SharedPtr<Cursor> cursor = SharedPtr<Cursor>(new Cursor(context_));
	cursor->SetStyleAuto(ui->GetRoot()->GetDefaultStyle());
	cursor->SetShape(cursorNames[type]);
	ui->SetCursor(cursor);
}

I tried to change cursor at the end of the frame but that didn’t help.

Modanung

Have you tried the first method without the last call to SetCursor ?

It might be an unexpected/unhandled situation and should be unnecessary in this case. I believe SetCursor may remove the only counted reference of the cursor you’re holding a pointer to. If so, the function could use an if (cursor == cursor_) return; at the beginning.

UI::SetCursor
void UI::SetCursor(Cursor* cursor)
{
    // Remove old cursor (if any) and set new
    if (cursor_)
    {
        rootElement_->RemoveChild(cursor_);
        cursor_.Reset();
    }
    if (cursor)
    {
        rootElement_->AddChild(cursor);
        cursor_ = cursor;

        IntVector2 pos = cursor_->GetPosition();
        const IntVector2& rootSize = rootElement_->GetSize();
        const IntVector2& rootPos = rootElement_->GetPosition();
        pos.x_ = Clamp(pos.x_, rootPos.x_, rootPos.x_ + rootSize.x_ - 1);
        pos.y_ = Clamp(pos.y_, rootPos.y_, rootPos.y_ + rootSize.y_ - 1);
        cursor_->SetPosition(pos);
    }
}
Modanung

Indeed this causes a segmentation fault:

UI* ui{ GetSubsystem<UI>() };
ui->SetCursor(new Cursor(context_));

ui->SetCursor(ui->GetCursor());

Taqer

Works, thanks :slightly_smiling_face:
Also its important to first set cursor in UI.

Modanung

Nice!

PR made: