`egui` has been an on-and-off weekend project of mine since late 2018. I am grateful to any help I can get, but bear in mind that sometimes I can be slow to respond because I am busy with other things!
You want to contribute to egui, but don't know how? First of all: thank you! I created a special issue just for that: <https://github.com/emilk/egui/issues/3742>. But make sure you still read this file first :)
[Issues](https://github.com/emilk/egui/issues) are for bug reports and feature requests. Issues are not for asking questions (use [Discussions](https://github.com/emilk/egui/discussions) or [Discord](https://discord.gg/vbuv9Xan65) for that).
For small things, just go ahead an open a PR. For bigger things, please file an issue first (or find an existing one) and announce that you plan to work on something. That way we will avoid having several people doing double work, and you might get useful feedback on the issue before you start working.
It is very easy to add complexity to a project, but remember that each line of code added is code that needs to be maintained in perpetuity, so we have a high bar on what get merged!
* Breaking changes are documented in the PR description
* The code should be readable
* The code should have helpful docstrings
* The code should follow the [Code Style](CONTRIBUTING.md#code-style)
Note that each new egui release have some breaking changes, so we don't mind having a few of those in a PR. Of course, we still try to avoid them if we can, and if we can't we try to first deprecate old code using the `#[deprecated]` attribute.
While using an immediate mode gui is simple, implementing one is a lot more tricky. There are many subtle corner-case you need to think through. The `egui` source code is a bit messy, partially because it is still evolving.
* Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)
* Add blank lines around all `fn`, `struct`, `enum`, etc
*`// Comment like this.` and not `//like this`
* Use `TODO` instead of `FIXME`
* Add your github handle to the `TODO`:s you write, e.g: `TODO(emilk): clean this up`
* Avoid `unsafe`
* Avoid `unwrap` and any other code that can cause panics
* Use good names for everything
* Add docstrings to types, `struct` fields and all `pub fn`
* Add some example code (doc-tests)
* Before making a function longer, consider adding a helper function
* If you are only using it in one function, put the `use` statement in that function. This improves locality, making it easier to read and move the code
* When importing a `trait` to use it's trait methods, do this: `use Trait as _;`. That lets the reader know why you imported it, even though it seems unused
* Avoid double negatives
* Flip `if !condition {} else {}`
* Sets of things should be lexicographically sorted (e.g. crate dependencies in `Cargo.toml`)
meaning there are two physical screen pixels for each logical point.
Angles are in radians, and are measured clockwise from the X-axis, which has angle=0.
### Avoid `unwrap`, `expect` etc.
The code should never panic or crash, which means that any instance of `unwrap` or `expect` is a potential time-bomb. Even if you structured your code to make them impossible, any reader will have to read the code very carefully to prove to themselves that an `unwrap` won't panic. Often you can instead rewrite your code so as to avoid it. The same goes for indexing into a slice (which will panic on out-of-bounds) - it is often preferable to use `.get()`.