Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to notify dragdrop source event once in imgui loop ? #5910

Closed
ChivenZhang opened this issue Nov 22, 2022 · 9 comments
Closed

How to notify dragdrop source event once in imgui loop ? #5910

ChivenZhang opened this issue Nov 22, 2022 · 9 comments
Labels
drag drop drag and drop

Comments

@ChivenZhang
Copy link

ChivenZhang commented Nov 22, 2022

Just a Question. I want to add dragdrop source event into my message system. But i can't do this, as imgui would loop many times.
The code as below. Can anyone help?

if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
{
	auto data = (u8)CastRef(this);
	if (ImGui::SetDragDropPayload("imgui", &data, sizeof(data), ImGuiCond_None))
	{
		// !!! Here notify lots of times during one dragdrop action. 
		// What I want is to notify only once. Can I make it?
		onDragDroped(Event{ EventType::GUI_DRAG_UP, (u8)CastRef(this) });
	}
	ImGui::Text(m_IconText.getValue().c_str());
	ImGui::EndDragDropSource();
}
@ocornut ocornut added the drag drop drag and drop label Nov 22, 2022
@PathogenDavid
Copy link
Contributor

It's not clear from your description what the issue is.

SetDragDropPayload returns true when your payload is accepted, after which BeginDragDropSource should also stop returning true as the user is no longer dragging the associated widget.

Please create a minimal repro that we can copy+paste into one of the example apps.

@ChivenZhang
Copy link
Author

ChivenZhang commented Nov 23, 2022

It's not clear from your description what the issue is.

SetDragDropPayload returns true when your payload is accepted, after which BeginDragDropSource should also stop returning true as the user is no longer dragging the associated widget.

Please create a minimal repro that we can copy+paste into one of the example apps.

SetDragDropPayload returns true whenever I drag up the source widget, So It will notify event many times, if I don't drop the source widget. I want to let it notify event once during the time I drag up the widget.

The image below shows what problem I met when using event system : drag up many times and drop once.

image

image

@PathogenDavid
Copy link
Contributor

Oh, sorry. I misremembered some of the details of how SetDragDropPayload works. (I forgot it also returned true for "Could be accepted if user stopped dragging".)

I don't think there's a super clean way to do this without poking at internals, the easiest solution would be to keep track of some extra state to identify if the payload was accepted during the previous frame when BeginDragDropSource stops returning true. For example:

static bool lastFrameWasAccepted = false; // You probably don't want to use a static local in your actual app, this is just an example.)
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
{
	auto data = (u8)CastRef(this);
	lastFrameWasAccepted = ImGui::SetDragDropPayload("imgui", &data, sizeof(data), ImGuiCond_None);
	ImGui::Text(m_IconText.getValue().c_str());
	ImGui::EndDragDropSource();
}
else if (lastFrameWasAccepted)
{
	lastFrameWasAccepted = false;
	onDragDroped(Event{ EventType::GUI_DRAG_UP, (u8)CastRef(this) });
}

@ChivenZhang
Copy link
Author

I'll try it later, thanks.

@ocornut
Copy link
Owner

ocornut commented Nov 23, 2022

It is unclear what you are trying to achieve with your GUI_DRAG_UP event. When it is supposed to be triggered, what is the purpose of it? What do you want to happen if you drag a payload over one destination, then move over another?

Two notes:

  • You can check if GetDragDropPayload() == NULL to know if one has already been submitted.
  • You can call SetDragDropPayload() with ImGuiCond_Once which will have a pretty similar effect as the above.

So I suspect in your case this may be enough:

if (ImGui::GetDragDropPayload() == NULL)
{
    ImGui::SetDragDropPayload("imgui", &data, sizeof(data), ImGuiCond_Once);
    onDragDroped(Event{ EventType::GUI_DRAG_UP, (u8)CastRef(this) }); 
}

Note of this checks if the payload is being "accepted" but if you were to be interested in that information, your GUI_DRAG_UP/GUI_DRAG_DOWN protocol is not going to be enough.

@PathogenDavid
Copy link
Contributor

It is unclear what you are trying to achieve with your GUI_DRAG_UP event. When it is supposed to be triggered, what is the purpose of it? What do you want to happen if you drag a payload over one destination, then move over another?

My interpretation is they want their event to fire once when the payload is dropped. IE: The payload was accepted, a call somewhere to AcceptDragDropPayload returned said payload, and the user is no longer dragging.

I do agree though, it's not totally clear.

  • You can call SetDragDropPayload() with ImGuiCond_Once which will have a pretty similar effect as the above.

Maybe I'm missing something, but cond here has to do with how Dear ImGui handles copying the payload and doesn't affect what SetDragDropPayload returns.

if (ImGui::GetDragDropPayload() == NULL)

My understanding is this condition can never be true within a BeginDragDropSource block as when BeginDragDropSource always sets ImGuiContext::DragDropActive to true before returning true, which means GetDragDropPayload won't return null.

@ocornut
Copy link
Owner

ocornut commented Nov 23, 2022

but cond here has to do with how Dear ImGui handles copying the payload and doesn't affect what SetDragDropPayload returns.

Correct.

My understanding is this condition can never be true within a BeginDragDropSource block as when BeginDragDropSource always sets ImGuiContext::DragDropActive to true before returning true, which means GetDragDropPayload won't return null.

Also correct, but I think this constitute a bug of GetDragDropPayload() then, it should be NULL before the first payload has been submitting. I will look into fixing this. Thanks!

ocornut added a commit that referenced this issue Nov 23, 2022
…before payload is submitted. (#5910, #143)

+ Added test "widgets_dragdrop_new_payloads" in Test Suite.
ocornut added a commit to ocornut/imgui_test_engine that referenced this issue Nov 23, 2022
@ocornut
Copy link
Owner

ocornut commented Nov 23, 2022

Pushed fix for GetDragDropPayload() not returning NULL 856c631 + test ocornut/imgui_test_engine@0446c87fe

@ChivenZhang
Copy link
Author

ChivenZhang commented Nov 23, 2022

Pushed fix for GetDragDropPayload() not returning NULL 856c631 + test ocornut/imgui_test_engine@0446c87fe

I can't thank you too much, thanks every one. It runs well. (one drag up, one drop down)

20221124034606.mp4

kjblanchard pushed a commit to kjblanchard/imgui that referenced this issue May 5, 2023
…before payload is submitted. (ocornut#5910, ocornut#143)

+ Added test "widgets_dragdrop_new_payloads" in Test Suite.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
drag drop drag and drop
Projects
None yet
Development

No branches or pull requests

3 participants