Unnamed Zig Library (raymenuz, devmenuz)?

Zig + raylib + raygui Developer Mode Library

No source yet

I really like raylib for making games.

This is my order of operations when learning a new language:

  1. Hello, World
  2. Hello, World in Raylib
  3. Diffusion-Limited Aggregation simulation using Raylib

I kinda like raygui , raylib’s GUI library. The things I don’t like about raygui are more of a symptom of what I suspect raysan’s philosophy is: make things that do one thing well. Battery’s, such as GUI element adjustment without recompiling, are not included.

I’m proposing a library for Zig projects using raylib and raygui to allow me to point to a text file in code and have it produce a corresponding developer GUI.

Hopefully usage will look like the following

    pub const Player = struct {
        collision: boolean,
        properties: struct {
            jumpHeight: f32
        }        
    };
    
    pub const GameState = struct {
        player: *Player,
        npcs: struct {
            spawnCount: i16
        },
        fn resetPlayerPostion() void {
            ...
        }
        
    };

    const devMenu = DevMenu(GameState).init("main_dev_menu.yaml", &state, PLAYFIELD_HEIGHT, PLAYFIELD_WIDTH);
    devMenu.draw();
playerMenu:
  - slider: # raygui element type
      name: jumpHeight
      type: f32 # Zig type of value
      valuePath: player.properties.jumpHeight # path to 

  - toggle: 
      name: noClip
      type: bool
      valuePath: player.collision
      
  - textBox:
      name: npcCount
      type: i16
      valuePath: npcs.spawnCount
  - button:
      name: resetPlayerPosition
      functionPath: resetPlayer
          

Motivation:

  • Package my usual raygui boilerplate for raylib projects
    • GUI element listing and placement math
  • Allow GUI adjustments without recompiling
    • Ordering
    • Widget Sizes
    • Number Ranges
  • Gain a deeper understanding of Zig
    • reflection system
    • comptime system
    • tests
Update 1/1/2025

After being quarantined from my family with COVID for 4 days with very little else to do, I’m very excited about where this project is at. I’m happy with what I’ve learned from this project. I’m accepting of the compromises I had to make that stemmed from my lack of knowledge of zig and its reflection system.

Completed so far

I have a system in place that can support i32, f32, types for raygui elements.

I have the raygui Label(i32, f32), Slider(f32), and Value Box(i32) elements implemented. Each element has been easier than the last to implement.

The dev menu drawing settings are also completed, so I can adjust the positioning of the menu with having to recompile, which is nice.

Everything is parsed from a yaml file using ymlz which I made my first open source project contribution to :)

Compromises

Optionals and enums aren’t supported by ymlz at the moment. When parsing a yaml list to an array a structs, all fields must be present on the list objects that are defined in the struct. If they aren’t, memory becomes misaligned and field values are missing. This means fields like range that are required for value ranges on Sliders and ValueBoxes are also required, but not used, for Label elements

I also hoped for my generic arguments to allow me to avoid drawIntElements and drawFloatElements patterns but having only three types, with only two more in mind at the moment, means that it isn’t that big of a burden.

What I’ve gained

Zig muscle memory for captures, tagged unions, error handling.

An intuition on zig’s comptime system. No one should ask me questions about it, but if someone showed me a comptime stack trace from the compiler I might be able to figure it out.

Confidence to contribute to open source projects.

What I want for the future

Clean this up and publish it in its own repo. I think that could be very soon as a v0.1.0.

I want this thing covered in tests. I for the number of troubles I’ve had with memory and parsing related errors, I should have been leaning on tests more as opposed to std.debug.print statements everywhere to figure them out. Everything is currently in two large files at the moment, one for building the definitions of the menu and one for turning those definitions into the menu items. I think the size coupled with zig’s ability to have tests in any file, and my desire to use that, has made writing tests more cumbersome than they should be.

I would like to document the do’s, don’t’s, and gotcha’s, especially with writing the yaml files. If I can have helpful errors for when users do something I know they will do that will break the yaml parsing, that could suffice.

I want to figure out how to publish this as an artifact for zig’s build. In the end, users should be able to do a zig fetch and have it available as a module. I’m sure this will be done with CI actions, but outside of that I have no idea what that will look like.

I would like all raygui elements usable with as many supported types as possible. If I could enable multiple menus, wrapping elements in windows, that would be neat but definitely not necessary.