Big changes for Kludgine - Removing over 10k lines in one PR

Today, I merged this pull request:

Despite the name, I’m not done with a rewrite. If you’ve been following along, I try to keep pull requests manageable. If you look at the stats of the above you might notice a couple of alarming things:

  1. This pull request nets negative 11,897 lines of code.
  2. Kludgine had that many lines of code?!

Yes, Kludgine had become a beast. Even after these changes, the Kludgine repository weighs in at 5,860 lines of Rust code, according to tokei. Ultimately this beast is what led me to search for other means of writing a game. I liked a lot of how the consumer API worked, but the under-the-hood code was hard to test.

What was removed? These are the features that were ripped out:

  • All user interface code.
  • All user code is not async now. After more evaluation, tools like flume provide excellent abstractions that allow async and non-async code to interact more freely. wgpu still requires some async for initialization and mapping buffers, but outside of that, standard threading is used. Each window gets its own thread.
  • Text rendering has been stripped to its core: there are still easy-to-use types for including/loading fonts, but you can only draw one font per API call. Styled text rendering will be coming back via a separate crate – more details below.

This leaves Kludgine's responsibilities clear: windowing (including multi-window support) and rendering. To me, this project isn’t done, and I wanted to talk about how all these thousands of lines are going to return, but with a better tested and more modular approach.

User Interface

When brainstorming with @dAxpeDDa about approaching writing user interfaces, we weren’t just talking about Cosmic Verge. We were thinking about providing excellent experience building apps using PliantDb.

One aspect that we haven’t built out is the HTTP service. I want PliantDb to be able to easily host a single-page application built with Rust over HTTP built into the PliantDb server. Not only will Cosmic Verge clients connect to PliantDb, will also be hosted by PliantDb.

We already knew we wanted to support a fairly extensive amount of user interface elements in Cosmic Verge, so it wasn’t far off to think how we could use those same user interface elements to build our internal tools – which would need to read and write from PliantDb. In thinking of the average user, if it’s a developer building an app and they want to target the browser, they will want to have a native DOM experience.

To put that in more clear terms, Kludgine rendering the user interface via wgpu is not what those users would want. They would want their text inputs to be <input> tags.

This is what motivated me to consider the user interface project separate from Kludgine. It took us much longer to come around to the idea of completely relying on Gooey for Cosmic Verge.

Text Editing/Rendering

One portion of code that had a reasonable amount of code coverage was text wrapping. I was pleased with my implementation of wrapping and rich text handling. However, the rich text APIs were powered by styles, which were deeply integrated within user interface code that was ripped out. That’s the main reason for this code vanishing: stylecs became the new home for the style types, and Gooey owns the style components such as TextColor.

Since gooey-kludgine relies on Kludgine. I couldn’t make Kludgine depend on gooey-core for the style components. This presents a fun problem.

gooey-rasterizer exists to allow Gooey to support other winit-driven applications as long as they can provide a Renderer trait implementation. This Renderer trait matches the basic text rendering and measurement APIs of JavaScript and Kludgine’s new limited API. For the web browser, it’s already decided that the text input widget will be <input> tags, but how will it be implemented for the Rasterizer?

My current plan is to introduce a new set of crates by extracting the Renderer types into the main crate of this new “high-level rendering” API crate. Much of Kludgine's old text wrapping code will be reintroduced but rewritten to work with the high-level rendering API. These new crates will be what gooey-rasterizer uses behind the scenes to power its text input widget.

There’s still a lot of problems to be solved, but I think this general approach should yield a nice result:

  • Kludgine will regain rich-text drawing via these new crates, without relying on Gooey.
  • Gooey will support text input using native DOM elements in the browser and be able to support it using Kludgine or any other hypothetical Renderer implementation when using the native executables with a Rasterizer.

Offscreen Rendering and Unit Tests

The last thing I wanted to share is that Kludgine has its first rendering unit test. After calling it a night yesterday, I thought I was working on one of two things in the morning, but my mind was nagging me about Gooey not having unit tests yet.

For unit testing the rasterizer, I could implement a mock Renderer that recorded each operation and inspect the calls being made. I probably will take this exact approach. But, it doesn’t really prove the visual result met expectations.

As I started thinking about what it might take to implement offscreen rendering, I realized it might get me closer to another goal: supporting rendering Gooey in an arbitrary wgpu application. @dAxpeDDa convinced me a while ago that for Gooey to be any level of success, we would want to support integration into any wgpu application. After coffee this morning, I started whittling away at the problem and have a pretty straightforward example showing it off.

The example isn’t quite as simple as I would like it to be, but my main goal was to get it working today. It’s not good enough to use with another wgpu application yet – technically, you could, but it’d be more expensive than necessary. When I finish the arbitrary wgpu integration, you’ll receive wgpu::Texture that you can render in your application.

The path to 0.1.0

I’m kind of embarrassed. I released v0.0.2 on Sept. 30, and then I haven’t updated it since. Instead of labeling this release 0.0.3, since it’s such a major departure from the 0.0.x series’ APIs, I will be releasing this reduced API as 0.1.0.

With this reduced API front, I want to spend some time writing basic documentation for what remains and cleaning up some of the APIs as I work through that process.

Unlike in January, I’m now excited again at the prospects of Kludgine and how it fits into the big picture of Cosmic Verge as well as my dream “app development platform” with PliantDb.

1 Like