diff --git a/examples/app.py b/examples/app.py new file mode 100644 index 00000000..9f347394 --- /dev/null +++ b/examples/app.py @@ -0,0 +1,140 @@ +from pathlib import Path +from collections import OrderedDict + +import wgpu +from imgui_bundle import imgui +from wgpu.gui.auto import WgpuCanvas, run +from wgpu.utils.imgui import ImguiRenderer +import subprocess + + +canvas = WgpuCanvas(title="imgui", size=(1200, 900)) +adapter = wgpu.gpu.request_adapter_sync(power_preference="high-performance") +device = adapter.request_device_sync() + +imgui_renderer = ImguiRenderer(device, canvas) + +example_paths: OrderedDict[Path, list[Path]] = OrderedDict() + +# grab all examples as a dict of lists, {example_dir: [e1.py, e2.py, ...]} +for d in sorted(Path(__file__).parent.glob("*")): + if d.is_dir(): + if d.name.startswith("."): + continue + if d.name in ["tests", "screenshots"]: + continue + example_paths[d] = sorted(d.glob("*.py")) + +# the first example +example_dir0 = list(example_paths.keys())[0] +example0 = example_paths[example_dir0][0] + +# set the first example to be selected +selection = (example_dir0, example0) + +# read the first example +with open(selection[1], "r") as f: + example_src = f.read() + +# used to determine if a different example has been selected between frame draws +new_selection: bool = False + + +def update_gui(): + global selection + global new_selection + global example_src + + example_double_clicked = False + + w, h = canvas.get_physical_size() + imgui.new_frame() + + menu_size = (340, h) + menu_pos = (0, 0) + + imgui.set_next_window_size(menu_size) + imgui.set_next_window_pos(menu_pos) + + flags = imgui.WindowFlags_.no_collapse | imgui.WindowFlags_.no_resize + + # window with the list of all examples + imgui.begin("Examples", None, flags=flags) + + # add menu item for each example + for example_dir in example_paths.keys(): + # each example dir + imgui.text(example_dir.name) + imgui.indent(10) + + # each individual example + for example in example_paths[example_dir]: + is_selected = selection[0] == example_dir and selection[1] == example + selection_changed, selected = imgui.selectable(example.name, p_selected=is_selected) + + # update selection dir and path if this example file is selected + if selected: + selection = (example_dir, example) + # if double-clicked, used to flag running the example + if imgui.is_mouse_double_clicked(0): + example_double_clicked = True + + if selection_changed: + # new example file is selected on this frame update + new_selection = True + + imgui.unindent(10) + imgui.separator() + + imgui.end() + + # window that displays text of example + source_window_size = (w - menu_size[0], h) + imgui.set_next_window_size(source_window_size) + imgui.set_next_window_pos((menu_size[0], 0)) + + imgui.begin(f"{selection[0].name}/{selection[1].name}", None, flags) + + # path to the selected example file + selected_example = selection[1] + + # if this example file has just been selected in this render frame update + # then update the example_src by reading the file from disk + if new_selection: + with open(selected_example, "r") as f: + example_src = f.read() + + # new_selection = False prevents it from reading from disk every time the frame is rendered + # this allows any changes from the user to be kept, while the file on disk remains unchanged + # so the user can make a small change to the file in the text editor and run it with the changes! + new_selection = False + + # basic text editor + src_changed, example_src = imgui.input_text_multiline(".", example_src, (source_window_size[0], h - 60)) + + clicked = imgui.button("Run example") + + # run the example if the button is clicked or if the item is double-clicked + if clicked or example_double_clicked: + subprocess.Popen(["python", "-c", example_src]) + + imgui.end() + + imgui.end_frame() + imgui.render() + + return imgui.get_draw_data() + + +# set the GUI update function that gets called to return the draw data +imgui_renderer.set_gui(update_gui) + + +def draw_frame(): + imgui_renderer.render() + canvas.request_draw() + + +if __name__ == "__main__": + canvas.request_draw(draw_frame) + run()