Skip to content

Commit

Permalink
Work on tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Dec 19, 2024
1 parent dcd6bee commit 35c4105
Show file tree
Hide file tree
Showing 2 changed files with 540 additions and 170 deletions.
189 changes: 19 additions & 170 deletions tutorial/discover_immediate_gui.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,28 @@
"\n",
"The example below illustrates this concept, where an application could display a counter, together with a button to increase it:\n",
"\n",
"![example](images/demo_immediate.png)\n",
"\n",
"**Python**:\n",
"```python\n",
"# on_frame is called at each frame\n",
"def on_frame():\n",
" # Display a text widget \n",
" imgui.text(f\"counter={counter}\")\n",
" imgui.text(f\"Counter: {counter}\")\n",
" # Display a button, and return true if clicked\n",
" if imgui.button(\"increase counter\"):\n",
" if imgui.button(\"Increment\"):\n",
" counter += 1 # Perform an action immediately on interaction\n",
"```\n",
"\n",
"**C++**:\n",
"```cpp\n",
"void on_frame() { \n",
" ImGui::Text(\"Counter: %d\", counter);\n",
" if (ImGui::Button(\"Increment\"))\n",
" counter++;\n",
"}\n",
"```\n",
"\n",
"### Why Use Immediate Mode GUIs?\n",
"\n",
"Here are some key benefits:\n",
Expand Down Expand Up @@ -58,193 +70,30 @@
"- **[Dear ImGui](https://github.com/ocornut/imgui)**: A lightweight and fast C++ library for Immediate Mode GUI programming, with over 60k stars on GitHub. It enables rapid creation of UI components such as buttons, sliders, and text fields with minimal code, leveraging GPU rendering for exceptional performance.\n",
"- **[Hello ImGui](https://pthom.github.io/hello_imgui)**: A powerful C++ wrapper around Dear ImGui designed to streamline apps creation with Dear ImGui, and to simplify complex tasks such as layout handling, FPS idling, and creating mobile and desktop applications. It reduces boilerplate and adds enhanced utilities, making it ideal for both simple prototypes and advanced production-grade GUIs.\n",
"- **[Dear ImGui Bundle](https://pthom.github.io/imgui_bundle)**: an extensive set of ready-to-use widgets and libraries, based on ImGui and Hello ImGui. It also provides bindings for Python, enabling you to create GUI applications in **Python**, which we will explore in this tutorial.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Installing the required Libraries\n",
"\n",
"*In this web tutorial, `imgui-bundle` is pre-installed*. If you are running this tutorial locally, you can install imgui-bundle following the instructions [for Python](https://pthom.github.io/imgui_bundle/install_python.html) or [for C++](https://pthom.github.io/imgui_bundle/install_cpp.html).\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Hello Dear ImGui: your first application with Dear ImGui\n",
"\n",
"Let's start by creating a simple application \"Hello, World\" application, where we will demonstrate several aspects of ImGui and Hello ImGui.\n",
"\n",
"In this application:\n",
"- The world is represented by an image of the Earth globe (using `hello_imgui.image_from_asset`)\n",
"- The globe size can be adjusted using a slider. This part of the code demonstrates how to handle user editions with ImGui widgets: in Python bindings, widgets return a tuple `(changed, new_value)`, where changed indicates if the widget was interacted with.\n",
"- A counter can also be incremented by clicking a button\n",
"- The Frame rate is displayed, as a way to demonstrate how Hello ImGui automatically handles application idling.\n",
"- An application State class is created, as an illustration of how to separate the application logic from the GUI logic.\n",
"- We use Hello ImGui \"Run\" function to start the application.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from imgui_bundle import imgui, hello_imgui, ImVec2\n",
"\n",
"# Define a class to hold the application state\n",
"class AppState:\n",
" counter = 0\n",
" globe_size = 100.0\n",
"\n",
"\n",
"# This is our GUI function, which will be called by Hello ImGui at *every* frame:\n",
"# It will display the GUI of our application *and* handle user events\n",
"def gui(app_state: AppState):\n",
" global counter, globe_size\n",
"\n",
" # Step 1: Display a label and an image\n",
" # -------------------------------------\n",
" # Display a label saying \"Hello, \" and an image of the world below\n",
" imgui.text(\"Hello, \")\n",
" # Will display an image from the \"assets/\" folder, with a size of (app_state.globe_size, 0) (0 means keep the aspect ratio)\n",
" # (see )\n",
" hello_imgui.image_from_asset(\"images/world.png\", ImVec2(app_state.globe_size, 0))\n",
"\n",
" # Step 2: Display a slider and handle its value changes\n",
" # -----------------------------------------------------\n",
" # Display a slider to change the globe size\n",
" # Some widgets in ImGui will occupy the full width of the window by default, \n",
" # so we can use set_next_item_width to limit the width\n",
" imgui.set_next_item_width(hello_imgui.em_size(10))\n",
" # In Python, ImGui widgets often return a tuple of (value_changed: bool, new_value: ...), hence we store\n",
" # Note: this is specific to Python bindings (See next part to see how to handle this in C++)\n",
" _changed, app_state.globe_size = imgui.slider_float(\"Globe size\", app_state.globe_size, 50.0, 400.0)\n",
"\n",
" # Step 3: Display a counter and a button to increment it\n",
" # ------------------------------------------------------\n",
" imgui.separator_text(\"Counter\")\n",
" imgui.text(\"Counter: %d\" % app_state.counter)\n",
" imgui.same_line()\n",
" if imgui.button(\"Increment\"):\n",
" app_state.counter += 1\n",
"## Deploy web applications in Python with Dear ImGui Bundle\n",
"\n",
" # Step 4: Display the frame rate\n",
" # ------------------------------\n",
" # Display the application frame rate, with an indication if the application is idling:\n",
" # (by default, Hello ImGui will let applications idle after 3 seconds of inactivity)\n",
" imgui.separator_text(\"Frame rate\")\n",
" imgui.text(f\"{hello_imgui.frame_rate(): .1f} FPS\")\n",
" if hello_imgui.get_runner_params().fps_idling.is_idling:\n",
" imgui.same_line() # By default, widgets will be placed on the next line, unless we call imgui.same_line() before.\n",
" imgui.text(\"(Idling)\")\n",
"\n",
" # Step 5: Demonstrate different themes\n",
" # ------------------------------------\n",
" imgui.separator_text(\"Themes\")\n",
" tweaked_theme = hello_imgui.get_runner_params().imgui_window_params.tweaked_theme\n",
" if imgui.button(\"Cherry\"):\n",
" tweaked_theme.theme = hello_imgui.ImGuiTheme_.cherry\n",
" hello_imgui.apply_tweaked_theme(tweaked_theme)\n",
" imgui.same_line()\n",
" if imgui.button(\"Darcula Darker\"):\n",
" tweaked_theme.theme = hello_imgui.ImGuiTheme_.darcula_darker\n",
" hello_imgui.apply_tweaked_theme(tweaked_theme)\n",
" imgui.same_line()\n",
" if imgui.button(\"White is White\"):\n",
" tweaked_theme.theme = hello_imgui.ImGuiTheme_.white_is_white\n",
" hello_imgui.apply_tweaked_theme(tweaked_theme)\n",
"\n",
"\n",
" # Step 6: Display a button to exit the application, with a tooltip\n",
" # ----------------------------------------------------------------\n",
" imgui.separator_text(\"Exit\")\n",
" note = \"\"\"\n",
" - In the case of a desktop application, setting \"app_shall_exit\" to True will close the window at the next frame.\n",
" - In the case of a web application (or a mobile phone application), this has no effect.\n",
" \"\"\" \n",
" if imgui.button(\"Exit\"):\n",
" hello_imgui.get_runner_params().app_shall_exit = True\n",
" imgui.set_item_tooltip(note)\n",
"\n",
"\n",
"def main():\n",
" # Create an instance of the application state\n",
" app_state = AppState()\n",
" # Create a parameterless function that calls the GUI function with the application state\n",
" gui_fn = lambda: gui(app_state)\n",
" # And let hello_imgui run our parameterless function\n",
" hello_imgui.run(gui_fn)\n",
"\n",
"if __name__ == \"__main__\":\n",
" main()"
"![Jack](images/jack_tangled_frameworks.jpg)\n",
"![Tom](images/tom_tangled_frameworks.webp)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Hello, Dear ImGui, in C++\n",
"\n",
"As an illustration, below is the C++ code to create this application using Dear ImGui and Hello ImGui.\n",
"\n",
"TODO: add a link to emscripten demo of this app. Explain how modified values are handled by the widgets.\n",
"\n",
"```cpp\n",
"#include \"imgui.h\"\n",
"#include \"hello_imgui/hello_imgui.h\"\n",
"## Installing the required Libraries\n",
"\n",
"int counter = 0;\n",
"*In this web tutorial, `imgui-bundle` is pre-installed*. If you are running this tutorial locally, you can install imgui-bundle following the instructions [for Python](https://pthom.github.io/imgui_bundle/install_python.html) or [for C++](https://pthom.github.io/imgui_bundle/install_cpp.html).\n",
"\n",
"void Gui() {\n",
" // To be continued...\n",
"}\n",
"\n",
"int main() { HelloImGui::Run(Gui); }\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Deploy web applications in Python with Dear ImGui Bundle\n",
"\n",
"![Jack](images/jack_tangled_frameworks.jpg)\n",
"![Tom](images/tom_tangled_frameworks.webp)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# What's next?\n",
"\n",
"* Explore more widgets within ImGui (buttons, inputs, plots)\n",
"* Explore even more widgets withing Dear ImGui Bundle (e.g., plots, 3D guizmo, advanced image viewer, etc.)\n",
"* Learn about Hello ImGui: docking layouts (e.g., for advanced UIs).\n",
"* ... and much more!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
Expand Down
Loading

0 comments on commit 35c4105

Please sign in to comment.