summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md164
1 files changed, 164 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..988a52e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,164 @@
+# minimgui
+
+Experimental immediate-mode GUI without IDs.
+
+# Libraries
+
+- [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h)
+- [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h)
+
+# Scope And Purpose
+
+This is mostly just a proof-of-concept. It's not intended to be used for serious work yet.
+There's currently just a software backend, so no accelerated graphics yet.
+Currently, only Linux + X11 is supported.
+
+IMGUIs typically come in two forms:
+ - Dear ImGui-like: functions either explicitly accept an ID argument or use
+ static arguments (like labels) to generate an ID. The obvious problems
+ are that the user has to manually make sure the IDs are unique, since
+ using the same ID multiple times will cause issues. Serious
+ implementations use an ID stack to mitigate this, however, it can still
+ cause issues:
+ [Dear ImGui FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system)
+ - Unity-like: Unity's IMGUI implicitly assigns incremental IDs that reset every frame.
+ This fixes the problem of always needing a unique value and simplifies the API.
+ However, IDs are still used, it's just largely opaque to the user.
+ Because of the per-frame incremental nature of IDs, aliasing can happen dynamically
+ depending on which code path is executed, which is very annoying to debug and fix,
+ since you have to increase the ID counter by the exact amount necessary
+ to make up for the omitted GUI calls, which isn't always 1:1, since more complex calls
+ might use multiple IDs.
+
+The reason conventional IMGUIs use IDs is that they need to 1. remember
+state across frames and 2. detect when one UI element hides another. The first
+problem is trivially solved by pushing the responsibility of storing state onto
+the user, so IDs aren't strictly necessary here. This might seem like more
+work for the user, but in practice, anywhere there's state, the user's already
+storing some data. For example, text-fields require the user to store the
+string anyway, so using a state object as opposed to a string doesn't add
+complexity for the user. The only difference is that he now needs to access the
+field of a struct (or call a toString() method) to access the string, instead
+of storing the string directly. The second problem is more subtle. Take the
+following pseudocode:
+```
+rect = getSomeRect();
+if (button("Button 1", rect))
+ print("Button 1 pressed");
+if (button("Button 2", rect))
+ print("Button 2 pressed");
+```
+Both Button 1 and 2 are in the same position on the screen, but with back-to-front
+rendering, Button 2 is drawn on top. However, the code for Button 1 executes first,
+so the implementation can't just return true if the cursor is inside Button 1's
+bounds. In practice, IMGUIs have some sort of `clicked_id` and `propagated_click_id`.
+When the user clicks, the code for Button 1 runs, which sets `propagated_click_id`
+to "Button 1", then the code for Button 2 runs, which sets `propagated_click_id`
+to "Button 2". At the end of the frame, `clicked_id` is set to the last value of
+`propagated_click_id` (in this case "Button 2"), and then, on the next frame,
+`button("Button 2", rect)` will return true.
+
+There is a related, more complex, aliasing/desync bug that mostly occurs when dealing
+with text input fields/areas in Unity-like (incremental) IMGUIs:
+Even when the user stores the states of input elements,
+some level of arbitration between the inputs is necessary to avoid situations like
+multiple input fields being focused simultaneously. So the library internally stores
+the ID of the currently focused element, which leads to the aforementioned problems
+with IDs changing depending on which code paths are taken, leading to focus changing
+seemingly at random.
+
+Minimgui completely eliminates IDs.
+This is done by rendering front-to-back, instead of the usual back-to-front.
+If we simply declare that elements will be rendered front-to-back, "Button 1"
+can just return true (and set some internal `click_consumed` bool to inhibit
+following elements from handling clicks), since it's the top-most element.
+This has two benefits: Firstly and most obviously, we no longer need IDs. Secondly,
+we no longer have a 1-frame delay, since we immediately know whether an element
+was clicked. Of course, conventional IMGUIs can mitigate this in all
+sorts of ways: Unity does multiple GUI passes, which also allows automatically managing
+more complex layouts (though in practice this is difficult to work with). Some implementations
+do a hit test on click-start and return the hit result on click-end, though of course
+this complicates internals and reduces flexibility.
+
+While front-to-back might seem awkward, at the end of the day it's just a different
+convention, and all the weirdness from having to dispatch rendering commands
+backwards is limited to low-level internal functions that most users will never
+interact with. So the only thing that changes from an API point-of-view is that
+the user no longer needs to worry about IDs or aliasing, and the mental model
+of drawing one element on top of another is replaced by drawing one element
+behind another.
+
+# Roadmap
+
+- [x] Figure out a way to have an imgui without IDs
+- [x] Implement MVP
+ - [x] Rectangle
+ - [x] Image
+ - [x] Click
+ - [x] Drag and Drop
+ - [x] Rudimentary Text
+- [ ] Port to MS Windows
+- [ ] Add OpenGL backend
+- [ ] Clean up project
+ - [ ] Separate input handling library from project
+ - [ ] Separate window handling library from project
+ - [ ] Isolate Backends
+ - [ ] Remove example/testing app
+
+# Build
+
+Requires zig 0.15
+
+## As Executable (and run)
+
+```
+git clone git.vandorp.lu/minimgui
+cd minimgui
+zig build -Demit-exe
+zig-out/bin/minimgui
+```
+
+## As Library (C-ABI)
+
+```
+git clone git.vandorp.lu/minimgui
+cd minimgui
+zig build -Demit-lib
+```
+
+# Examples
+
+See src/app/app.zig, bindings/main.c, and bindings/main.py
+
+# Contributing
+
+If you have any ideas or issues, send them to steven@vandorp.lu.
+
+If you want to modify code, make your changes in a separate branch,
+generate the patch(es) (`git format-patch master` from inside your branch)
+and send the patch file(s) to steven@vandorp.lu.
+
+# License
+
+MIT License
+
+Copyright (c) 2026 Steven Van Dorp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+