Skip to content

Commit

Permalink
Examples: refactor all examples with a MainLoopStep() function, to fa…
Browse files Browse the repository at this point in the history
…cilitate use with Emscripten. (#2492, #3699)

Aligned all examples.
  • Loading branch information
ocornut committed Feb 2, 2023
1 parent b51919d commit 96ab68e
Show file tree
Hide file tree
Showing 18 changed files with 1,321 additions and 1,151 deletions.
4 changes: 4 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ All changes:
Latest Emscripten seems to emit correct values.
- Backend: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation).
(#6117, #4116, #3632) [@tonygrue, @bfierz]
- Examples: refactord all examples to use a "MainLoopStep()" function. This is in order
to be able to trivially make some compile with Emscripten. (#2492, #3699)
While not all examples are expected to compile on Emscripten, we try to keep all of them
as close as possible to each others.
- Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call
DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted
when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx]
Expand Down
148 changes: 83 additions & 65 deletions examples/example_allegro5/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@
#include "imgui.h"
#include "imgui_impl_allegro5.h"

// Forward declarations of helper functions
bool MainLoopStep(ALLEGRO_DISPLAY* display, ALLEGRO_EVENT_QUEUE* queue);

// Main code
int main(int, char**)
{
// Setup Allegro
al_init();
al_install_keyboard();
al_install_mouse();
al_init_primitives_addon();

// Create window with graphics context and event queue
al_set_new_display_flags(ALLEGRO_RESIZABLE);
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
al_set_window_title(display, "Dear ImGui Allegro 5 example");
Expand Down Expand Up @@ -60,86 +66,98 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);

bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

// Main loop
bool running = true;
while (running)
while (true)
{
if (!MainLoopStep(display, queue))
break;
}

// Cleanup
ImGui_ImplAllegro5_Shutdown();
ImGui::DestroyContext();
al_destroy_event_queue(queue);
al_destroy_display(display);

return 0;
}

bool MainLoopStep(ALLEGRO_DISPLAY* display, ALLEGRO_EVENT_QUEUE* queue)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
bool done = false;
ALLEGRO_EVENT ev;
while (al_get_next_event(queue, &ev))
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
ALLEGRO_EVENT ev;
while (al_get_next_event(queue, &ev))
ImGui_ImplAllegro5_ProcessEvent(&ev);
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
done = true;
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
{
ImGui_ImplAllegro5_ProcessEvent(&ev);
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
running = false;
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
{
ImGui_ImplAllegro5_InvalidateDeviceObjects();
al_acknowledge_resize(display);
ImGui_ImplAllegro5_CreateDeviceObjects();
}
ImGui_ImplAllegro5_InvalidateDeviceObjects();
al_acknowledge_resize(display);
ImGui_ImplAllegro5_CreateDeviceObjects();
}
}
if (done)
return false;

// Start the Dear ImGui frame
ImGui_ImplAllegro5_NewFrame();
ImGui::NewFrame();
// Start the Dear ImGui frame
ImGui_ImplAllegro5_NewFrame();
ImGui::NewFrame();

// 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!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// Our state
// (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow)
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
// 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!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);

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

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

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

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

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

// 3. Show another simple window.
if (show_another_window)
{
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)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}

// Rendering
ImGui::Render();
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));
ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
al_flip_display();
// 3. Show another simple window.
if (show_another_window)
{
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)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}

// Cleanup
ImGui_ImplAllegro5_Shutdown();
ImGui::DestroyContext();
al_destroy_event_queue(queue);
al_destroy_display(display);
// Rendering
ImGui::Render();
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));
ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
al_flip_display();

return 0;
return true;
}
126 changes: 66 additions & 60 deletions examples/example_android_opengl3/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,72 @@ static char g_LogTag[] = "ImGuiExample";
static std::string g_IniFilename = "";

// Forward declarations of helper functions
static void Init(struct android_app* app);
static void Shutdown();
static void MainLoopStep();
static int ShowSoftKeyboardInput();
static int PollUnicodeChars();
static int GetAssetData(const char* filename, void** out_data);

void init(struct android_app* app)
// Main code
static void handleAppCmd(struct android_app* app, int32_t appCmd)
{
switch (appCmd)
{
case APP_CMD_SAVE_STATE:
break;
case APP_CMD_INIT_WINDOW:
Init(app);
break;
case APP_CMD_TERM_WINDOW:
Shutdown();
break;
case APP_CMD_GAINED_FOCUS:
case APP_CMD_LOST_FOCUS:
break;
}
}

static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
{
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
}

void android_main(struct android_app* app)
{
app->onAppCmd = handleAppCmd;
app->onInputEvent = handleInputEvent;

while (true)
{
int out_events;
struct android_poll_source* out_data;

// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
{
// Process one event
if (out_data != NULL)
out_data->process(app, out_data);

// Exit the app by returning from within the infinite loop
if (app->destroyRequested != 0)
{
// shutdown() should have been called already while processing the
// app command APP_CMD_TERM_WINDOW. But we play save here
if (!g_Initialized)
Shutdown();

return;
}
}

// Initiate a new frame
MainLoopStep();
}
}

void Init(struct android_app* app)
{
if (g_Initialized)
return;
Expand Down Expand Up @@ -125,13 +186,14 @@ void init(struct android_app* app)
g_Initialized = true;
}

void tick()
void MainLoopStep()
{
ImGuiIO& io = ImGui::GetIO();
if (g_EglDisplay == EGL_NO_DISPLAY)
return;

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

void shutdown()
void Shutdown()
{
if (!g_Initialized)
return;
Expand Down Expand Up @@ -228,63 +290,7 @@ void shutdown()
g_Initialized = false;
}

static void handleAppCmd(struct android_app* app, int32_t appCmd)
{
switch (appCmd)
{
case APP_CMD_SAVE_STATE:
break;
case APP_CMD_INIT_WINDOW:
init(app);
break;
case APP_CMD_TERM_WINDOW:
shutdown();
break;
case APP_CMD_GAINED_FOCUS:
break;
case APP_CMD_LOST_FOCUS:
break;
}
}

static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
{
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
}

void android_main(struct android_app* app)
{
app->onAppCmd = handleAppCmd;
app->onInputEvent = handleInputEvent;

while (true)
{
int out_events;
struct android_poll_source* out_data;

// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
{
// Process one event
if (out_data != NULL)
out_data->process(app, out_data);

// Exit the app by returning from within the infinite loop
if (app->destroyRequested != 0)
{
// shutdown() should have been called already while processing the
// app command APP_CMD_TERM_WINDOW. But we play save here
if (!g_Initialized)
shutdown();

return;
}
}

// Initiate a new frame
tick();
}
}
// Helper functions

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

0 comments on commit 96ab68e

Please sign in to comment.