MENU EDITOR
MOTIVATION
The idea of making a menu editor was born during the creation of the second game project me and my team made using our own engine. During our previous projects our graphic designers haven’t had a lot of control over the placement of the UI-elements used in the game, always being dependent on a programmer to adjust placement and appearance. I wanted to create a editor to give them more freedom editing the UI-elements using our custom Engine.
I’ve been enjoying the process of working with tools during our projects, but since it’s something that’s not directly visible in the final product it hasn’t been at the top of the prioritation queue to develop. Therefore I saw this as an opportunity to finally be able to spend more time on working on something behind the scenes.
TOOL Menu-editor
TIMEFRAME 6 weeks (20h/week)
ENGINE In-House (Friendship Engine)
GOALS
Make it possible for anyone in the team to set up Menus, and to iterate further on them
Make it easy to add new sprites, text and other elements a menu might contain
Find a simple solution to add and edit functions to the executable elements such as buttons
PROCESS
When planning a project, I prefer starting with a rough sketch of what I need to reach my goals. This I usually do by using an online whiteboard or using a classic pen and paper, not too detailed but just enough to get an idea of all the parts I’ll need for my project.
After that was done I needed an environment to work in that was not going to be effected by work being done in the engine. We were in the process of refactoring the rendering pipeline and I wanted to be able to work independently, merging my project later on when everyting is stable and done. I created a branch of the engine, added an extra module, and worked from there.
THE EDITOR
Since I had done the setup for the ImGui used in our game engine, the base was already set for me to build on further. I took some inspiration from Unity’s interface and naming doing this setup, knowing that this was something we were all familiar working with in previous projects and I wanted to make it as user friendly as possible.
One thing I had some issues with in this stage was the “Menu View” window. Due to the way our rendering pipeline was engineered and the docking branch of Dear ImGui not liking sprites with alpha values < 1 (picking up the ImGui-window’s background color in the transparency) I solved this temporarily by rendering the menu directly onto the main viewport instead. This also became the final solution, since this turned out working just fine.
BUILDING THE COMPONENT SYSTEM
We’re using a Entity Component System in our engine, but after a bit of research and based on the fact that at the time we did not have control over the systems render order, I decided to create my own component system for the menu objects. I thought this would be easier to work with keeping it separated entirely from the ECS to have more control in general.
The purpose of using a component system was to use them as building blocks, a empty base object with a certain set of components attached would together create, for example, a button.
-
This is the base entity, I decided to name it MenuObject not to confuse it with the ECS. The Object can have three different states: default, hovered and pressed. But the state can only change when the objects has a ColliderComponent attached to it.Description text goes here
-
Pretty self explanatory, but this is the component containing the sprites. It can have three different textures and colors for the MenuObject’s different states. You can also edit attributes such as size, position, or pivot.
-
Produces a text to display anywhere in the menu, can be used on top of a button, as a title, or anything you would need text for in your menu. Fonts, size and color is editable.
-
I debated on what to name this component, but ultimately I went with Collider2DComponent, which looks a bit clunky but it’s descriptive. This determines the clickable area of the object. You can change size and postion as you want.
-
The command component determines what will happen when I press a button. I had some plans starting out that this would be combined with visual scripting, since this was something I implemented in our engine as well. But I decided that this would not be necessary (and perhaps a classic case of over engineering) so I went with using function pointers instead.
-
This was my last edition to the editor, it did not turn out quite as planned and ended up being a little bit rushed. Not really being used as intended in the final version. You can read more about why in the improvements section.
THE MENU HANDLER
The MenuHandler’s main responsibilities are updating and rendering the MenuObjects. It also contains a stack, to handle the different sub-menus that’s been created using a state stack design pattern.
It’s also handling the loading and saving the menu to/from JSON-files. The saving part could technically be moved elsewhere since it’s only used when editing a menu, but for simplicity I decided to keep them in the same class, so it’s easier to find for future iteration.
ID-MANAGER
I use a ID-manager to create unique ID’s for each object. It’s basically just a bitset and it keeps track of and distributes a ID that’s not already in use.
DRAG & DROP
I wanted to make it as easy as possible for our graphic designers to add their assets into the editor (and the game), so I added a Drag & Drop function. With this they can simply drag the item they wish to add into the window, and it will be loaded into a editor asset database for use. Right now it only takes .dds and .ttf, since these are the formats we have been using in our game but it’s easy to iterate on if more would be added.
IMPROVEMENTS
After a quick rundown of the editor together with the graphic designer responsible for the UI, they immediately got to work. I asked them to report to me as soon as they walked into eventual bugs or if there was any features they wished could be added. The feedback I got was very valuable and I added and changed a few things after receiving it. An example was to be able to change text color depending on the object’s states, which was something I’d never thought of during the creation process.
One thing I never found the time to add was a CommandPattern to be able to Undo/Redo the edits you’ve just made. This would make it even more user friendly. But, I haven’t worked with this pattern in this way before and after researching it a bit it seemed to be a lot to implement in hindsight. I decided to leave it out for now, but I will do more research on this since it will surely come up again.
Another thing that would be a huge improvement but was added a little too late was the InteractableComponent. What I wanted was to sort of “animate” the components, for example a slider that has a grab and a fill area should be interactable when changing the value, this was easier in theory than the actual implementation and it did not turn out as I wanted it to. I will continue working on that part, and hopefully get it to work as intended in our next game project.
FINAL THOUGHTS
Although there’s still room for improvement, the editor gets the job done and it was used (by someone other than me) to create the menus for one of our games! In the planning process I was definitely guilty of “over engineering”, and got a little carried away at times adding features that might not even end up being used. One way to avoid this in the future would be to ask for feedback earlier in the process, steering the focus back into the right direction. But all in all, I’m very happy with how the editor turned out! I had fun making it, and I’m looking forward to more projects like this.