Jump to content
  • Advertisement
Sign in to follow this  
Finalspace

C++ ImGui questions

This topic is 419 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am playing around with ImGui, adding a UI to my level editor, but i am having trouble with mouse clicks in ImGui triggers a click in my actual editor (Because it uses the same input states).

Right know i have just a main menu bar and the editor rendering is behind that. When i click on a menuitem for example, and select another sub item and click, i place a block in my editor - just because the input events are the same for both ImGui and my editor.

So i have a few questions:

1.) Is there a way to detect when ImGui has taken any action/hover in the previous frame, so i can skip the input handling for my editor? (This way i can prevent the issue i have right now)

2.) Can i add a imgui window which fully fits the rest of the entire screen - after a main bar has been added? (Do i manually need to calculate the size?)

3.) Should i make the entire editor with ImGUI only - so i wont get any input fuzziness problems?

Share this post


Link to post
Share on other sites
Advertisement

1) When calling ImGui::NewFrame() it is updating the io.WantCaptureMouse and io.WantCaptureKeyboard fields. You can use those fields to hide the inputs from your own application/editor. The most obvious case is that io.WantCaptureMouse will be true when hovering an ImGui window (in reality the logic is a little more complex than that, it tracks clicks/drags and active widgets).

This is answered in the FAQ under "Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?"

2) You can use ImGui::SetNextWindowPos, ImGui::SetNextWindowSize(). You do need to manually calculate the size but you can also create one fullscreen window (position = 0,0, size = io.DisplaySize) with a MenuBar, it's equivalent to creating a main menu bar.

3) I don't know what "input fuzziness" means. It should be fine to create an entire editor, many people have been doing that. One limitation of imgui with it handles inputs events is that if you expect to run at very low frame rates (e.g. 10 FPS) you will want to create a queue events and defer passing all of them to imgui at once (e.g. if you received 2 clicks in one frame). This should be handled by the library but eventually but it's not at the moment. If you don't expect to be running at super low framerate it won't be a problem.

 

Share this post


Link to post
Share on other sites
8 hours ago, ocornut said:

1) When calling ImGui::NewFrame() it is updating the io.WantCaptureMouse and io.WantCaptureKeyboard fields. You can use those fields to hide the inputs from your own application/editor. The most obvious case is that io.WantCaptureMouse will be true when hovering an ImGui window (in reality the logic is a little more complex than that, it tracks clicks/drags and active widgets).

This is answered in the FAQ under "Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?"

2) You can use ImGui::SetNextWindowPos, ImGui::SetNextWindowSize(). You do need to manually calculate the size but you can also create one fullscreen window (position = 0,0, size = io.DisplaySize) with a MenuBar, it's equivalent to creating a main menu bar.

3) I don't know what "input fuzziness" means. It should be fine to create an entire editor, many people have been doing that. One limitation of imgui with it handles inputs events is that if you expect to run at very low frame rates (e.g. 10 FPS) you will want to create a queue events and defer passing all of them to imgui at once (e.g. if you received 2 clicks in one frame). This should be handled by the library but eventually but it's not at the moment. If you don't expect to be running at super low framerate it won't be a problem.

 

Thanks, that clears it up.

 

Now i have another one, which is also about preventing click events to happen after a imgui menuitem has been clicked.

I have built a simple level editor with imgui and its set a tile in the corner always when i load a level from the main menu - just because the click of the MenuItem is still true. Can i consume that click somehow?

		void Game::EditorUpdate() {
			auto io = ImGui::GetIO();
			auto ctx = ImGui::GetCurrentContext();
			auto editorWindowSize = ImVec2(io.DisplaySize.x, io.DisplaySize.y);

			ImGui::SetNextWindowSize(editorWindowSize, ImGuiSetCond_Always);
			ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiSetCond_FirstUseEver);
			const char *mapName = activeEditorFilePath.empty() ? "Unnamed map" : activeEditorFilePath.c_str();

			ImGui::Begin(mapName, nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_MenuBar);

			// Menu
			if (ImGui::BeginMenuBar()) {
				if (ImGui::BeginMenu("File")) {
					if (ImGui::MenuItem("New map")) {
						ClearLevel();
						activeEditorFilePath = "";
					}
					if (ImGui::MenuItem("Load map...")) {
						showOpenDialog = true;
						firstTimeOpenDialog = true;
					}
					if (ImGui::MenuItem("Save map")) {
						showSaveDialog = activeEditorFilePath.empty();
						if (!showSaveDialog)
							SaveMap(activeEditorFilePath.c_str());
						else
							firstTimeSaveDialog = true;
					}
					if (ImGui::MenuItem("Save map as...")) {
						showSaveDialog = firstTimeSaveDialog = true;
					}
					if (ImGui::MenuItem("Exit")) {
						exitRequested = true;
					}
					ImGui::EndMenu();
				}
				ImGui::EndMenuBar();
			}

			// Canvas area
			auto maxRegion = ImGui::GetWindowContentRegionMax();
			auto minRegion = ImGui::GetWindowContentRegionMin();
			auto regionSize = ImVec2(maxRegion.x - minRegion.x, maxRegion.y - minRegion.y);
			const ImVec2 startCursorPos = ImGui::GetCursorScreenPos();

			RenderArea canvasArea = {};
			UpdateRenderArea(canvasArea, regionSize.x, regionSize.y, HalfGameWidth, HalfGameHeight, GameAspect);
			const f32 canvasTileSize = TileSize * canvasArea.scale;

			ImDrawList* draw_list = ImGui::GetWindowDrawList();

			const ImVec2 canvasViewportStart = ImVec2(startCursorPos.x + canvasArea.viewportOffset.x, startCursorPos.y + canvasArea.viewportOffset.y);
			const ImVec2 canvasViewportEnd = ImVec2(canvasViewportStart.x + canvasArea.viewportSize.w, canvasViewportStart.y + canvasArea.viewportSize.h);
			draw_list->AddRect(canvasViewportStart, canvasViewportEnd, ImColor(255, 255, 0));

			// Draw tiles
			for (u32 y = 0; y < TileCountForHeight; ++y) {
				u32 tileY = (TileCountForHeight - 1 - y);
				for (u32 x = 0; x < TileCountForWidth; ++x) {
					const Tile &tile = tiles[tileY * TileCountForWidth + x];
					if (tile.isSolid) {
						f32 tx = canvasViewportStart.x + x * canvasTileSize;
						f32 ty = canvasViewportStart.y + y * canvasTileSize;
						draw_list->AddRectFilled(ImVec2(tx, ty), ImVec2(tx + canvasTileSize, ty + canvasTileSize), ImColor(255, 0, 0));
					}
				}	
			}

			// Mouse hover and click actions
           	// HERE I DONT WANT TO TAKE ANY CLICK ACTION AFTER A MENU ITEM HAS BEEN CLICKED 
			if (ImGui::IsWindowFocused() && ImGui::IsMouseHoveringRect(canvasViewportStart, canvasViewportEnd)) {
				auto mp = ImGui::GetMousePos();
				s32 hoverTileX = (s32)((mp.x - canvasViewportStart.x) / canvasTileSize);
				s32 hoverTileY = (s32)((mp.y - canvasViewportStart.y) / canvasTileSize);
				f32 tx = canvasViewportStart.x + hoverTileX * canvasTileSize;
				f32 ty = canvasViewportStart.y + hoverTileY * canvasTileSize;
				draw_list->AddRect(ImVec2(tx, ty), ImVec2(tx + canvasTileSize, ty + canvasTileSize), ImColor(255, 255, 0));

				u32 invertHoverTileY = (TileCountForHeight - 1 - hoverTileY);
				if (ImGui::IsMouseDown(0)) {
					SetTile(hoverTileX, invertHoverTileY, true);
				} else if (ImGui::IsMouseDown(2)) {
					SetTile(hoverTileX, invertHoverTileY, false);
				}
			}

			ImGui::End();
		}

 

Edited by Finalspace

Share this post


Link to post
Share on other sites
1 hour ago, ocornut said:

Are you running on latest? There was a bug in 1.51 which I think is what you are having here.

For general imgui questions may I suggest asking in the imgui github, this is where all the other questions are being asked.

https://github.com/ocornut/imgui/issues

Oh great, never thought it may be a bug... After updating to the latest everything seems to work properly now.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!