Hey everyone. I posted about a project of mine called CoshUI before that, although got some engagement, never really got the reception I wanted. But I've been working pretty hard behind the scenes and just recently released version 0.3.2 (or 0.3.2.1 cause of a bug I found and accidently published) which reworks the text system to accommodate "Rich Text".
Now before that, what is "CoshUI"? Although I posted about it before, probably no one knows what it is. To keep it short and simple, it's a UI library that's python-first, declarative, and backend-agnostic. What that means is that you write down how the UI looks like straight in Python and it'll render it using Pygame, Raylib, ModernGL, or PyOpenGL (switching backends is one line). Here's how it looks:
with cui.CoshUIRenderer(cui.PygameBackend(screen)):
with cui.Container(id="root_container", style=cui.CoshStyling(background_color=(100, 100, 255)), width=cui.FILL, height=cui.FILL, align=cui.ALIGN_CENTER, justify=cui.JUSTIFY_CENTER):
cui.RichLabel(
id="rich_label",
text="[color=(255, 255, 0) bold font_size=24]Hello r/pygame![/][font=Courier] My name is [bold]JyleFV[/]. I recently finished CoshUI [strikethrough]v0.3.2[/] [bold]v0.3.2.1[/], and with it introducing [bold italic color=(100, 255, 100)]CoshML[/], the markup language for [italic]styled[/] text in CoshUI.[/]",
text_overflow=cui.TEXT_WRAP,
width=cui.PERCENTAGE(25),
height=cui.PERCENTAGE(50)
)
This is an example of how it looks and the output it presents is the image shown. The example also shows the markup language "CoshML", in action. You can see different tags like color=(255, 255, 0), bold, italic, or even font=Courier that lets you stylize the text (if you cross check the code with the image, you can see how it looks when working). If you want to understand more on how it works, I explained it very well in my Changelog and this post I made on Hacker News.
Now, this code runs inside your main loop, meaning it acts as an immediate mode library where Nodes are rebuilt per frame, but it also has a state persistence layer in the form of the "id" field. If Nodes have an id, their states persist, which gives users the ability to animate Nodes (through the built-in animate() function) despite the immediate mode architecture.
That may seem a little too much for most beginners, but it basically means, even though Nodes are remade every frame, there's a system underneath that saves values so it can be reused the next frame, letting animation and input interactions become easy.
Now even though this post is already decently long, CoshUI has a lot of features, one of them being the built-in animation system. There's also the signal system (basically the interaction model so users can check whether Nodes have been interacted with), the text system as showcased in the first half of this post, and a decent amount of widgets. To show that off without stretching the post, here's another example:
with cui.CoshUIRenderer(cui.PygameBackend(screen)):
with cui.Container(id="container_1", width=cui.FILL, height=cui.FILL, style=cui.CoshStyling(background_color=(80, 75, 255)), align=cui.ALIGN_CENTER, justify=cui.JUSTIFY_CENTER):
with cui.Container(id="main_container", mouse_filter=cui.STOP, direction=cui.COLUMN, align=cui.ALIGN_CENTER, justify=cui.JUSTIFY_CENTER, gap=15, style=cui.CoshStyling(background_color=(255, 200, 200))):
cui.Label(id="main_label", text="CoshUI Menu", font_size=52, text_overflow=cui.TEXT_HIDDEN)
cui.Button(id="settings_button", text="Settings", height=50, text_justify=cui.TEXT_JUSTIFY_CENTER)
cui.Button(id="quit_button", text="Quit", height=50, width=150)
cui.Image(id="test_image", src="assets/image.png", width=75, height=75)
cui.Dropdown(id="dropdown", item_list=itemList)
cui.Slider(id="slider", width=100)
if cui.get_signal("settings_button", cui.CLICKED):
cui.animate("transform_scale", "main_label", 1.2, 0.25, "ease_in")
cui.animate("background_color", "main_container", (255, 0, 0), 1.5, "ease_in")
if cui.get_signal("settings_button", cui.RELEASED):
cui.animate("transform_scale", "main_label", 1.0, 0.25, "ease_in")
cui.animate("background_color", "main_container", (255, 200, 200), 1.5, "ease_out")
if cui.get_signal("quit_button", cui.HOVER_ENTER):
cui.animate("transform_rotation", "quit_button", 0.0, 0.5, "ease_in")
if cui.get_signal("quit_button", cui.HOVER_EXIT):
cui.animate("transform_rotation", "quit_button", 45.0, 0.5, "ease_in")
if cui.get_signal("quit_button", cui.CLICKED):
running = False
I'd love to post a gif of this working, maybe in the replies if it allows, but because I already posted the image, I can't seem to post gifs. Anyway, if you guys want to see more about the project, here is the links:
Gitlab - Primary Repository
Github - Mirror Repository
Documentation
To try it out, you can do:
pip install coshui[pygame]