Activity

Glitchy

The main thing I did this time was set up the achievement pop up, which is what appears to let you know you’ve gotten an achievement. This required setting up both the Unity Project and adding a few things to the Core.
Unity Project
First I setup some key things like the Addressable Build Pipeline (Which I took with permission from https://github.com/wafflethings/WafflesWeapons/) and basic editor scripts (like a script to create an AchievementInfo). Then I had to actually create the pop up. To do this I took one of the existing UI elements in ULTRAKILL and modified it. I then created a test achievement using the previously mentioned editor script,
Core Changes
In the Core I started off with some basic refactoring and error handling improvements. Then all that was really left to get the pop up working was code to load the assets, and a script which determines the behavior of the popup
Attachment
The clip below shows a bit of gameplay I recorded showcasing what the popup looks like. For now it’s wired up to a key press but once I move on to the main Mod, ingame events can trigger the pop up instead.

0
Glitchy

I created the basics for the achievement system under the ‘Core’ C# project. The basics comprise of AchievementInfo classes and an AchievementManager
AchievementInfo
An AchievementInfo is a Unity Scriptable Object which stores basic information about your achievement, such as it’s display name and whether or not it has been completed. It can be inherited to create custom achievement types, such as ‘ProgressiveAchievementInfo’ which is an achievement which you can make progress towards (eg. 5/9 bosses killed).
AchievementManager
The achievement manager is what does most of the heavy lifting. It stores all registered achievements and saves/loads completion info from a binary file (achievements.dat). It is also what mod developers will use to mark achievements as complete, as the achievement manager will spawn a UI element based on the achievement info (not implemented yet).

Attachment
0
Glitchy

I’ve initialized a Unity project and a C# solution for the project. The Unity project is generated by Vanity Reprised, a tool which creates a Unity project in which ULTRAKILL assets can be modified and exported. The C# solution has 2 projects: A ‘Core’ which will have all the code which developers can interact with to add their own achievements. and a ‘Mod’ which has the achievements which I will create for ULTRAKILL.

The screenshot below shows the both DLLs being loaded by Bepinex (a mod loader).

Attachment
0
Glitchy

Shipped this project!

I built a tray utility which send system info to configured HID devices. I am really happy with the current version of the software, since my own HID devices work really well with it. The hardest part was definitely removing as much CGO as possible in order to make compiling easier on most platforms.

I want to work on it more, maybe by allowing devices to be plugged in at runtime or a configuration UI but for now everything is complete. I also want to improve Linux compatibility since it isn’t very good right now, as it relies on certain CLI software to be present.

Glitchy

I sorted out all the extra stuff you need to do whenever launching a project. This means I now have a completed README to describe the project, a LICENSES directory which links all the third party libraries/software I used along with their licenses, and an automatic release system which will build the software for all supported platforms whenever I push a version tag.

The only major thing which I would like to have is automatic building for x86-64 on macOS, but since fyne-io/systray requires CGO for macOS and GitHub doesn’t have a free runner for x86 macOS it’ll have to be left out for now.

Here’s a screenshot of what the tray looks like on all platforms

Attachment
0
Glitchy

I added 2 features to the tray which make the user experience better. The first is device status which will tell you whether or not the device is connected to the application. The second is a shortcut to open the config directory, since opening it manually is ever so slightly annoying. I also added icons to all the tray actions to make it look a bit better.

0
Glitchy

The actual code is now complete! Well there is still the tray features I want to add but that’s about it. Since there is a lot I did this time around I’ll split this into parts based on what changes I made.

Refactoring Code
This time around I refactored literally the entire codebase. Nearly every function has been changed in some way, whether it be small changes like variable names or parameters, or big changes like merging entire files. There are hardly any comments since I wanted the code itself to be clear enough to anyone trying to understand the code. The main exception to this rule is in purego code, where I have comments explaining which headers constants or data structures come from.

HID Updates
I swapped from “github.com/sstallion/go-hid” to “rafaelmartins.com/p/usbhid” since the former is written in CGO, while the latter is written in purego. Functionality is the exact same, the only differences are in the function definitions and data types. Only one minor change was made which is adding a magic hex header to all data which is sent, which allows a HID device identify whether data is being sent from KIN or some other source.

Tray Icon
I finally updated the tray icon to something more appropriate. I made 3 versions of the icon using Aseprite. The first is the primary version used on Windows and Linux in most situations. The second is a low resolution version which is used only on windows in Low-DPI situations. The third is a monochrome icon which MacOS uses as a NSImage template image. The new icon looks pretty decent on all platforms imo.

The demo attached uses my hackpad to demonstrate data being transmitted from device to my hackpad over HID, which is then logged through QMK.

0
Glitchy

I’ve swapped the info fetchers on MacOS and Windows to use purego instead of CGO. This also means that I’m no longer using a CLI tool like osascript on macs, which is cool I suppose. However to get cross compilation working, I will need to swap the hid library which is being used as the current one uses CGO and that’s no good.

I also plan on doing another cleanup of the codebase, while also documenting pretty much every function and variable because things are a bit messy in my opinion. Along with that I want to rename active_window to activeapp because that’s what it actually does, it tells you literally nothing about the window and only about the active application name. No idea what I was thinking when initially naming the folder. Finally I need to add features to the tray item since it’s a bit useless right now besides letting you know the application is running

Attachment
0
Glitchy

So I got windows working properly, though I think I’m going to change the architecture for most of the application. Before I talk about that, I removed MIQT since I decided against a proper UI, and a tray item can be accomplished by using a fyne package which doesn’t require CGO. I also moved all of the info fetchers into a folder called info, simply for convenience sake.

Currently I’m using a combination of CGO and windows syscalls in order to fetch the information we need. However I don’t really like using CGO since it makes building a huge pain on windows since you need a proper mingw setup. This also applies to other platforms, since one of the big benefits of Go is how easy it is to cross compile simply by setting GOOS. In theory this comes at a performance cost, since the only proper alternative to CGO us purego from what I have found. But since purego uses a lot of the same code as CGO for interacting with C, and the fact that the program is already extremely light weight, I think it’s acceptable.

Attachment
0
Glitchy

Linux works now! It is not done in the best way though. Right now I’m simply calling a CLI executable and filtering the output for what I want. On MacOS I still consider this acceptable since osascript is on literally every Mac. On Linux however so many configurations are possible that I would rather use CGO to support more platforms (specifically more wayland compositors). This means I will be rewriting in the future, but for now It’s perfectly fine while I work on Windows support.

Attachment
0
Glitchy

We now have a working config file! I decided on TOML since it’s arguably the most readable since it is practically an extended .ini file. I’ve not gotten configuration from UI working, but I’m not particularly attached to having a UI beyond a tray item so it’ll depend on whether I feel like it or not.

There was of course more refactoring as I moved stuff between folders in order to keep the codebase relatively clean and easy to read. I also made sure exiting is done properly through a dedicated shutdown function, since I don’t think anyone would appreciate a memory leak in the application.

There is not too much left which I want to do. I want to make something like an ARCHITECTURE.md file where I describe the application architecture for the sake of clarity. I’m also going to need to actually flesh out the README.md. Finally there’s cross-platform compatibility, which should be extremely simple in theory.

Attachment
0
Glitchy

So this is going to be a smaller project because I don’t have too many goals for the software.
I want it to be configurable so you can actually pick which device you want to send info to. I also want to be able to configure what data is sent, and what is not. It’s obviously going to work on the 3 main operating systems (MacOS, Windows, Linux Wayland/X11) since I personally use all 3 depending on the situation.

To that extent I’ve already got 2 of the main pieces of information I want to send, which is volume and the active application setup. I’ve also got sending the data over HID to a keyboard set at build time, but I haven’t gotten to the point where it’s configurable.

Not sure what picture to upload for this one, so I’ll go with the (most likely temporary) tray icon for the application (I set up a tray with MIQT)

Attachment
1

Comments

Glitchy
Glitchy about 2 months ago

I just realized that I misspelled it KID instead of KIN, so this is most definitely a very temporary tray icon

Glitchy

I ended up not making a custom graph widget because it would be really, really annoying to do so. But I did manage to clean up the graph to look just a bit better in my opinion, so I don’t have any issues with the built in graph widget anymore. Similarly I made the design for the memory breakdown a bit more clear by indenting some of the information when required

I also created an alternative graph which actually uses the platform specific data on MacOS to show a breakdown of memory used (App Memory, Compressed Memory and Wired Memory). It looks quite nice in my opinion. I do need to make some things more explicit in the UI by default though, like what the graphs represent and the unit on the Y-axis. I’m going to leave that for later though, since I want to get back to getting more system information. This time I’ll probably go for storage device information.

Attachment
Attachment
0
Glitchy

Creating the Memory UI was relatively smooth, seeing as a lot of it was just CPU UI code reused and changed a bit. Making the UI update when memory values change was also surprisingly easy due to go routines. I also made some visual tweaks to the CPU UI to make it look just a bit cleaner.

I’m going to change the graph eventually because QT Charts makes it really annoying to do what I want to do. This means I’ll have to make my own graph UI component, which shouldn’t be too hard (hopefully)

Attachment
0
Glitchy

I made quite a lot of changes this time, so I’m going to split them into points so it’s a bit easier to read.

  1. I refactored quite a bit of code into separate files, this means that one off pieces of code which are reused frequently or platform specific code have now been separated into different files. An example is cpu/cpu_info.go which has been split into cpu/info.go and cpu/info_darwin.go depending on if the code is useful everywhere, or only on MacOS (Note that the cpu_ prefix is gone).

  2. I introduced a few utilities which are probably going to be used a lot, one of which is conversion from Bytes to different formats up till Yottabytes, which is 10^15 GB. The other one is a simple wrapper for value unit pairs since it keeps code clean in info types like the one in memory/info.go

  3. I finally got around to adding a different type of system information, this time being Memory (RAM) info. Since not all info is relevant/existent on all platforms I created an interface called PlatformInfo, which can be implemented by different types to create unique info per platform as seen in memory/info_darwin.go T

The part I’m the most proud of is probably memory pressure, simply because I’ve not seen any information on the internet documenting what the boundaries for the different levels of memory pressure are (The colors on the memory pressure graph in activity monitor). It turns out it’s based on “System-wide memory free percentage” as seen when running the memory_pressure command. This value isn’t literally how much RAM is free but is based on other statistics which I can’t quite figure out.

Now I have to actually render all this information on screen. I quite like the way which Activity Monitor does it on MacOS so I’m going to go for something similar.

Attachment
1

Comments

Glitchy
Glitchy 2 months ago

I meant to publish this yesterday, I may have forgotten though.

Glitchy

I finally got the CPU info display looking pretty solid, landing on the horizontal grid for the core/cache info took longer than I would like to admit. I also can’t think of any other relevant CPU info which is available on MacOS, so I guess it’ll stay like this for now until I decide to revisit it.

Since CPU info is done, I’m going to implement some other type of info like GPU info, Memory info or Storage info, but I haven’t quite decided which I want to work on at the moment.

Attachment
0
Glitchy

I ended up splitting existing code into different folders to isolate different functionality, with the general idea that UI should be separate from information fetching, and that each section should get it’s on folder.

I also deleted the glow_image widget since I realized it would be way better to have a generic container widget which draws a border around children, since borders are a really important part of the UI to separate content explicitly.

There’s now a lot more CPU info being fetched, including core types (performance/efficiency), CPU cache information, and CPU code names. The UI has gotten to a point where I find it tolerable, but it still feels a bit off to me so I’m going to try different spacing between all the elements to see if I can get it to look better.

Attachment
0
Glitchy

Displaying the CPU info was pretty annoying, mainly because the way I implemented my GlowImage widget broke the border as soon as it was in a layout. I was able to fix it after using contents margin to declare that some space in the widget is used for decorations (the border), and in the process created some debug tools which will probably be useful for as long as I work on this.

I also took way too long to center everything vertically and horizontally, mainly because I didn’t realize that BoxLayouts like to use all the space if you don’t add stretch explicitly. Displaying the actual info on screen was relatively easy since I could just use QLabels in a VBoxLayout.

Next up is probably some styling to make the UI a bit better looking, along with fetching some more CPU info to display.

Attachment
0
Glitchy

So it’s my first time working with either Go or Qt so it’ll be a slow start to the progress logs I’m sure. Right now i want to focus on getting a decent looking UI, along with some static system information. I’ve implemented a bit of code which fetches basic CPU information on MacOS, and I’ve also created a custom widget which creates an image with a border around it.

Next up is probably to display the CPU info I fetched, along with other stuff like memory and storage configuration.

Attachment
0