Categories
Week 10

ImGui: Improving the Visual Debugger

This week, I continued my work on Director ImGui debugger from last week. Working on ImGui has been bit of a fun exercise since, it is an open canvas. There are a lot of opportunities to improve upon, and it all depends on what a developer might find useful while working on Director engine.

First of all, there were a bunch of impurities with the ImGui debugger. e.g.

  • Many child widgets have the same problem as the breakpoint window error pop-up from last week. i.e. widgets having the same label and id causing the ImGui throw an pop-up error saying changes made to one widget will be reflected to the other. I solved the same problem in the following places:
  • i.   Vars Window
    ii. Watched Variables
    iii. Scripts handler widget
  • I also improved the search for handler in the getHandler function. Instead of searching for the handler in all casts, we can single out the cast that has the handler in it.
  • When displaying Prop list in the execution handler window, there was a missing line, which I promptly added.

And a bunch of other small stuff, too small to be worth noting here.

Another feature that was stubbed in the debugger was being able to load and save the current state of the debugger into a persistent file. So, we can save a position in the game we are currently working on, and load the same position every time we start  a debugging session.
We went with the JSON format to store the state. We are currently storing the following things (and loading them back):
1) Window Positions
2) Score frame number
3) Windows that are open/closed
4) Global, Local and Watched Variables
5) Breakpoints
6) Log
7) Colors
Here, @OMGThePizzaGuy and @lephilousophe showed me `ImGui::SaveIniSettingsToMemory/ImGui::LoadIniSettingsFromMemory` which made my job much easier.

In the Watched Vars window, I am also showing Local Variables and Global Variables with different colors. On top of that, Local Variables that are out of scope are shown with different color.

All variables are now shown with `renderVariable()` which allows variables to be clicked on to add them to the WatchedVars list and also show their current value.

Previously, the Scripts window only showed the handler being executed at that moment. However, for better navigation, @sev suggested that all the scripts from the same lingo context should be shown in the same window. This took me a while. Since, now not only was I rendering multiple (ImGui) widgets for multiple (Director) windows, I was also showing rendering multiple handler in the same Scripts widget. This caused a bunch of problems with stepping over e.g. pressing step over caused the script to move multiple steps forward, and with showing the current line in the handler (with a little yellow arrow), because the _state->_dbg._isScriptDirty was getting set to false immediately after the first script was rendered. Also, the scroll to the current line was also not working. This took some time and debugging to fix.

When @sev started review on my PR, he immediately pointed out that I was making a separate ImGuiState::state for each window, which in hindsight I realized was a mistake. So, I reworked it to only make a separate instances of the objects that are needed to hold the execution context of a window. This also took a while to get right. There was a bunch of unexpected behavior including, the scripts were not showing up the first time the ‘step’ button was pressed in the control panel.

I also fixed a deprecation warning that occurred while compiling the Director engine. I had to create a custom copy constructor for the MacWindow class since the synthesized copy constructor was calling a deprecated copy constructor for the ManagedSurface class. Instead I had to use a copyFrom method as suggested.
There was another instance of use of deprecated method operator= for the ManagedSurface class, used copyFrom there as well.

Overall, a somewhat normal week. I hope to make even more improvements to the ImGui debugger. e.g. Adding a trace for watched variables is next on the list.

Categories
Week 9

Working on ImGui is fun!

This week I worked on some improvements on the ImGui visual debugger in the Director engine created by @sev. It allows us to see the lingo scripts being processed, cast members and their properties, score and a bunch of other stuff.

There was an extremely minor problem with the scripts window. The script window allows us to put breakpoints into the movie. However, the check boxes for the breakpoints were all being rendered with the same ID. ImGui has an label+ID system to name UI elements. Each new UI element must have a unique label+ID combination. Which was a simple mistake, rectified immediately.

The second thing was in case there are multiple windows, i.e. there are (Director) windows present other than the stage, then the ImGui just clubs all of the scripts being processed into a single (ImGui) Scripts window. So, we need to have a separate pane for the script being processed in each (Director) window.

For this, my idea was to create a separate `ImGui::_state` for each (Director) window and store them in a hashmap. Each time `showExecutionContext()` is called, we take the `ImGui::_state` for each window, and render them.
_state = getWindowState(stage);
updateCurrentScript();

Although, I ran into a multiple problems:
1. The execution context (ImGui) window once turned on, should stay turned on, but it was disappearing as soon as the (Director) window changes.
2. The control panel was debugging the script for the wrong (Director) window.
3. The other (ImGui) windows were being turned off whenever the (Director) window changes.
4. The multiple windows were showing the same script because the LingoState wasn’t changed in the global lingo context g_lingo.
5. The other panes were not showing any scripts because the `getHandler()` function wasn’t able to find the lingo script with the correct cast ID.
Solved these one by one and created a pull request yesterday.

Also, the callstack is currently a separate (ImGui) window. We also need to combine that with the scripts into a new (ImGui) window named the Execution Context. I did the refactoring. The Execution Context now looks like follows:

There was also a minor font rendering issue in the Score (ImGui) window. Apparently there were multiple breaking changes in the 1.92.0 update for ImGui regarding Font changes. However, it didn’t take long to figure out that it was just a one line change. I just had to set the `ImGui::IO::DefaultFont`, which is NULL by default. Previously when called:
ImGui::PushFont(ImGui::GetIO().DefaultFont)
The PushFont function would see that DefaultFont is NULL, and automatically push the first font added to using ImGui::AddTTF****. However, after the update, if the parameter to ImGui::PushFont is NULL, the font is unaffected and only the font size is changed. Hence, I had to manually make sure that ImGui::IO::DefaultFont is not NULL.

Overall, I didn’t feel stuck at any point. The process of figuring this out was smooth. However, this still took me a week to finish because I took an off day in the middle of the week. Also, due to my house hunt (which was a pain and a half) I used to start late @10PM IST and get tired by 2AM IST and doze off! Although I had written about it in my proposal, that I’ll have less time once my college starts, this is less than I had anticipated. This makes me worry about my GSoC project’s success. This week will be better, now that I (hopefully) have a stable abode. I’ll start consistently @6PM IST and put in 6-7 hours before calling it a day.

Here’s to hoping for a better week (again)!