Skip to content

Commit 96ab68e

Browse files
committed
Examples: refactor all examples with a MainLoopStep() function, to facilitate use with Emscripten. (#2492, #3699)
Aligned all examples.
1 parent b51919d commit 96ab68e

18 files changed

Lines changed: 1321 additions & 1151 deletions

File tree

docs/CHANGELOG.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ All changes:
9595
Latest Emscripten seems to emit correct values.
9696
- Backend: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation).
9797
(#6117, #4116, #3632) [@tonygrue, @bfierz]
98+
- Examples: refactord all examples to use a "MainLoopStep()" function. This is in order
99+
to be able to trivially make some compile with Emscripten. (#2492, #3699)
100+
While not all examples are expected to compile on Emscripten, we try to keep all of them
101+
as close as possible to each others.
98102
- Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call
99103
DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted
100104
when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx]

examples/example_allegro5/main.cpp

Lines changed: 83 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@
1616
#include "imgui.h"
1717
#include "imgui_impl_allegro5.h"
1818

19+
// Forward declarations of helper functions
20+
bool MainLoopStep(ALLEGRO_DISPLAY* display, ALLEGRO_EVENT_QUEUE* queue);
21+
22+
// Main code
1923
int main(int, char**)
2024
{
2125
// Setup Allegro
2226
al_init();
2327
al_install_keyboard();
2428
al_install_mouse();
2529
al_init_primitives_addon();
30+
31+
// Create window with graphics context and event queue
2632
al_set_new_display_flags(ALLEGRO_RESIZABLE);
2733
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
2834
al_set_window_title(display, "Dear ImGui Allegro 5 example");
@@ -60,86 +66,98 @@ int main(int, char**)
6066
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
6167
//IM_ASSERT(font != NULL);
6268

63-
bool show_demo_window = true;
64-
bool show_another_window = false;
65-
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
66-
6769
// Main loop
68-
bool running = true;
69-
while (running)
70+
while (true)
71+
{
72+
if (!MainLoopStep(display, queue))
73+
break;
74+
}
75+
76+
// Cleanup
77+
ImGui_ImplAllegro5_Shutdown();
78+
ImGui::DestroyContext();
79+
al_destroy_event_queue(queue);
80+
al_destroy_display(display);
81+
82+
return 0;
83+
}
84+
85+
bool MainLoopStep(ALLEGRO_DISPLAY* display, ALLEGRO_EVENT_QUEUE* queue)
86+
{
87+
// Poll and handle events (inputs, window resize, etc.)
88+
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
89+
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
90+
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
91+
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
92+
bool done = false;
93+
ALLEGRO_EVENT ev;
94+
while (al_get_next_event(queue, &ev))
7095
{
71-
// Poll and handle events (inputs, window resize, etc.)
72-
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
73-
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
74-
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
75-
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
76-
ALLEGRO_EVENT ev;
77-
while (al_get_next_event(queue, &ev))
96+
ImGui_ImplAllegro5_ProcessEvent(&ev);
97+
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
98+
done = true;
99+
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
78100
{
79-
ImGui_ImplAllegro5_ProcessEvent(&ev);
80-
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
81-
running = false;
82-
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
83-
{
84-
ImGui_ImplAllegro5_InvalidateDeviceObjects();
85-
al_acknowledge_resize(display);
86-
ImGui_ImplAllegro5_CreateDeviceObjects();
87-
}
101+
ImGui_ImplAllegro5_InvalidateDeviceObjects();
102+
al_acknowledge_resize(display);
103+
ImGui_ImplAllegro5_CreateDeviceObjects();
88104
}
105+
}
106+
if (done)
107+
return false;
89108

90-
// Start the Dear ImGui frame
91-
ImGui_ImplAllegro5_NewFrame();
92-
ImGui::NewFrame();
109+
// Start the Dear ImGui frame
110+
ImGui_ImplAllegro5_NewFrame();
111+
ImGui::NewFrame();
93112

94-
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
95-
if (show_demo_window)
96-
ImGui::ShowDemoWindow(&show_demo_window);
113+
// Our state
114+
// (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow)
115+
static bool show_demo_window = true;
116+
static bool show_another_window = false;
117+
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
97118

98-
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
99-
{
100-
static float f = 0.0f;
101-
static int counter = 0;
119+
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
120+
if (show_demo_window)
121+
ImGui::ShowDemoWindow(&show_demo_window);
102122

103-
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
123+
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
124+
{
125+
static float f = 0.0f;
126+
static int counter = 0;
104127

105-
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
106-
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
107-
ImGui::Checkbox("Another Window", &show_another_window);
128+
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
108129

109-
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
110-
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
130+
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
131+
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
132+
ImGui::Checkbox("Another Window", &show_another_window);
111133

112-
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
113-
counter++;
114-
ImGui::SameLine();
115-
ImGui::Text("counter = %d", counter);
134+
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
135+
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
116136

117-
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
118-
ImGui::End();
119-
}
137+
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
138+
counter++;
139+
ImGui::SameLine();
140+
ImGui::Text("counter = %d", counter);
120141

121-
// 3. Show another simple window.
122-
if (show_another_window)
123-
{
124-
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
125-
ImGui::Text("Hello from another window!");
126-
if (ImGui::Button("Close Me"))
127-
show_another_window = false;
128-
ImGui::End();
129-
}
142+
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
143+
ImGui::End();
144+
}
130145

131-
// Rendering
132-
ImGui::Render();
133-
al_clear_to_color(al_map_rgba_f(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w));
134-
ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
135-
al_flip_display();
146+
// 3. Show another simple window.
147+
if (show_another_window)
148+
{
149+
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
150+
ImGui::Text("Hello from another window!");
151+
if (ImGui::Button("Close Me"))
152+
show_another_window = false;
153+
ImGui::End();
136154
}
137155

138-
// Cleanup
139-
ImGui_ImplAllegro5_Shutdown();
140-
ImGui::DestroyContext();
141-
al_destroy_event_queue(queue);
142-
al_destroy_display(display);
156+
// Rendering
157+
ImGui::Render();
158+
al_clear_to_color(al_map_rgba_f(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w));
159+
ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
160+
al_flip_display();
143161

144-
return 0;
162+
return true;
145163
}

examples/example_android_opengl3/main.cpp

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,72 @@ static char g_LogTag[] = "ImGuiExample";
2121
static std::string g_IniFilename = "";
2222

2323
// Forward declarations of helper functions
24+
static void Init(struct android_app* app);
25+
static void Shutdown();
26+
static void MainLoopStep();
2427
static int ShowSoftKeyboardInput();
2528
static int PollUnicodeChars();
2629
static int GetAssetData(const char* filename, void** out_data);
2730

28-
void init(struct android_app* app)
31+
// Main code
32+
static void handleAppCmd(struct android_app* app, int32_t appCmd)
33+
{
34+
switch (appCmd)
35+
{
36+
case APP_CMD_SAVE_STATE:
37+
break;
38+
case APP_CMD_INIT_WINDOW:
39+
Init(app);
40+
break;
41+
case APP_CMD_TERM_WINDOW:
42+
Shutdown();
43+
break;
44+
case APP_CMD_GAINED_FOCUS:
45+
case APP_CMD_LOST_FOCUS:
46+
break;
47+
}
48+
}
49+
50+
static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
51+
{
52+
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
53+
}
54+
55+
void android_main(struct android_app* app)
56+
{
57+
app->onAppCmd = handleAppCmd;
58+
app->onInputEvent = handleInputEvent;
59+
60+
while (true)
61+
{
62+
int out_events;
63+
struct android_poll_source* out_data;
64+
65+
// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
66+
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
67+
{
68+
// Process one event
69+
if (out_data != NULL)
70+
out_data->process(app, out_data);
71+
72+
// Exit the app by returning from within the infinite loop
73+
if (app->destroyRequested != 0)
74+
{
75+
// shutdown() should have been called already while processing the
76+
// app command APP_CMD_TERM_WINDOW. But we play save here
77+
if (!g_Initialized)
78+
Shutdown();
79+
80+
return;
81+
}
82+
}
83+
84+
// Initiate a new frame
85+
MainLoopStep();
86+
}
87+
}
88+
89+
void Init(struct android_app* app)
2990
{
3091
if (g_Initialized)
3192
return;
@@ -125,13 +186,14 @@ void init(struct android_app* app)
125186
g_Initialized = true;
126187
}
127188

128-
void tick()
189+
void MainLoopStep()
129190
{
130191
ImGuiIO& io = ImGui::GetIO();
131192
if (g_EglDisplay == EGL_NO_DISPLAY)
132193
return;
133194

134195
// Our state
196+
// (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow)
135197
static bool show_demo_window = true;
136198
static bool show_another_window = false;
137199
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@@ -197,7 +259,7 @@ void tick()
197259
eglSwapBuffers(g_EglDisplay, g_EglSurface);
198260
}
199261

200-
void shutdown()
262+
void Shutdown()
201263
{
202264
if (!g_Initialized)
203265
return;
@@ -228,63 +290,7 @@ void shutdown()
228290
g_Initialized = false;
229291
}
230292

231-
static void handleAppCmd(struct android_app* app, int32_t appCmd)
232-
{
233-
switch (appCmd)
234-
{
235-
case APP_CMD_SAVE_STATE:
236-
break;
237-
case APP_CMD_INIT_WINDOW:
238-
init(app);
239-
break;
240-
case APP_CMD_TERM_WINDOW:
241-
shutdown();
242-
break;
243-
case APP_CMD_GAINED_FOCUS:
244-
break;
245-
case APP_CMD_LOST_FOCUS:
246-
break;
247-
}
248-
}
249-
250-
static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
251-
{
252-
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
253-
}
254-
255-
void android_main(struct android_app* app)
256-
{
257-
app->onAppCmd = handleAppCmd;
258-
app->onInputEvent = handleInputEvent;
259-
260-
while (true)
261-
{
262-
int out_events;
263-
struct android_poll_source* out_data;
264-
265-
// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
266-
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
267-
{
268-
// Process one event
269-
if (out_data != NULL)
270-
out_data->process(app, out_data);
271-
272-
// Exit the app by returning from within the infinite loop
273-
if (app->destroyRequested != 0)
274-
{
275-
// shutdown() should have been called already while processing the
276-
// app command APP_CMD_TERM_WINDOW. But we play save here
277-
if (!g_Initialized)
278-
shutdown();
279-
280-
return;
281-
}
282-
}
283-
284-
// Initiate a new frame
285-
tick();
286-
}
287-
}
293+
// Helper functions
288294

289295
// Unfortunately, there is no way to show the on-screen input from native code.
290296
// Therefore, we call ShowSoftKeyboardInput() of the main activity implemented in MainActivity.kt via JNI.

0 commit comments

Comments
 (0)