rP18399 moved the developer overlay from session.xml to developer_overlay.xml.
In rP22370/D1928, the developer overlay was refactored to use prototype syntax, remove XML duplication and move definitions to JS.
This patch revisits that commit in the course of #5387, addresses the following points:
* The checkbox definition is a function `getCommands` that returns an array of objects where each object returns a checkbox.
This approach is problematic in multiple ways.
(A) Mods can't extend the array if its the result of a function!
(B) Objects are limited to the few hardcoded functions. Class instances can add custom functions, subscribe them to events refs rP23076/D2378.
(C) It doesn't provide a `this` reference, so it is impossible to store a state variable.
By using an actual class instance per checkbox, we can store class helper variables per checkbox, such as the TimeWarp class or EntityState class.
* The benefit of using classes is to increase cohesion and separation of concerns.
Actually take this benefit by splitting things that are logically unrelated.
That is
1. the EntityState panel that shows the simstate of the selected entity.
That has nothing to do with the checkboxes and shouldn't dilute the class concerned with that.
2. TimeWarp mode is only relevant for one of the option, but the class in rP22370/D1928 now needs to be aware of that since its not split.
3. Splitting the class to handle one checkbox from the class to manage the panel. This allows making the checkbox states more simple, extensible and moddable.
* Filenames match their classname.
* Code uses class keyword.
* The TimeWarp code is moved from `input.js` from rP8803 to the TimeWarp setting using the hotkey release event from rP19028, refs #3194.
* Removes the global references to g_DeveloperOverlay and getters by accessing the players simstate.
* Moves EntityState to own XML file.
New classes:
```
class DeveloperOverlay
class DeveloperOverlayCheckbox
class DeveloperOverlayCheckboxes
class DeveloperOverlayEntityState
class TimeWarp
DeveloperOverlayCheckboxes.prototype.ControlAll = class
DeveloperOverlayCheckboxes.prototype.ChangePerspective = class
DeveloperOverlayCheckboxes.prototype.SelectionEntityState = class
DeveloperOverlayCheckboxes.prototype.PathfinderOverlay = class
DeveloperOverlayCheckboxes.prototype.ObstructionOverlay = class
DeveloperOverlayCheckboxes.prototype.UnitMotionOverlay = class
DeveloperOverlayCheckboxes.prototype.RangeOverlay = class
DeveloperOverlayCheckboxes.prototype.BoundingBoxOverlay = class
DeveloperOverlayCheckboxes.prototype.RestrictCamera = class
DeveloperOverlayCheckboxes.prototype.RevealMap = class
DeveloperOverlayCheckboxes.prototype.EnableTimeWarp = class
DeveloperOverlayCheckboxes.prototype.PromoteSelectedUnits = class
DeveloperOverlayCheckboxes.prototype.PromoteSelectedUnits = class
DeveloperOverlayCheckboxes.prototype.PromoteSelectedUnits = class
DeveloperOverlayCheckboxes.prototype.LockCullCamera = class
DeveloperOverlayCheckboxes.prototype.DisplayCameraFrustum = class
```
A performance optimization added in this patch is to extend the system from 23076/D2378 to support unsubscription from events.
This means we can save about 200 microsecnds each turn if the developer overlay is closed by unscubsribing from onSimulationUpdate if its closed!
(That's signficant, because the turn length may be 100ms eventually, so a no-op shouldnt consume 0.2% of each turn length.)
Measurement method:
```
lines=8
diff --git a/binaries/data/mods/public/gui/session/developer_overlay.js b/binaries/data/mods/public/gui/session/developer_overlay.js
index 57e9736fd8..6b1329ae93 100644
--- a/binaries/data/mods/public/gui/session/developer_overlay.js
+++ b/binaries/data/mods/public/gui/session/developer_overlay.js
@@ -210,11 +210,13 @@ DeveloperOverlay.prototype.toggle = function()
DeveloperOverlay.prototype.update = function()
{
+ let foo = Engine.GetMicroseconds();
let playerState = g_SimState.players[g_ViewedPlayer];
this.controlAll = playerState ? playerState.controlsAll : false;
this.updateValues();
this.updateEntityState();
+ warn(Engine.GetMicroseconds() - foo);
}
DeveloperOverlay.prototype.updateEntityState = function()
```
Measuremnet result (the 600microsecond numbers occur when showing the entity selection state):
```
lines=10
WARNING: 376
WARNING: 211
WARNING: 205
WARNING: 201
WARNING: 202
WARNING: 212
WARNING: 228
WARNING: 265
WARNING: 207
WARNING: 216
WARNING: 664
WARNING: 175
WARNING: 162
WARNING: 170
WARNING: 181
WARNING: 186
WARNING: 153
WARNING: 158
WARNING: 186
WARNING: 540
WARNING: 291
WARNING: 150
WARNING: 150
WARNING: 153
WARNING: 145
WARNING: 161
WARNING: 386
WARNING: 179
WARNING: 158
WARNING: 141
WARNING: 146
WARNING: 261
WARNING: 136
WARNING: 132
WARNING: 130
WARNING: 138
WARNING: 134
WARNING: 129
WARNING: 141
WARNING: 139
WARNING: 145
WARNING: 280
WARNING: 139
WARNING: 132
WARNING: 145
WARNING: 152
WARNING: 141
WARNING: 215
WARNING: 139
WARNING: 161
WARNING: 139
WARNING: 151
WARNING: 169
WARNING: 138
WARNING: 133
WARNING: 129
WARNING: 140
WARNING: 141
WARNING: 125
WARNING: 137
WARNING: 111
WARNING: 133
WARNING: 132
WARNING: 168
WARNING: 146
WARNING: 135
WARNING: 124
WARNING: 125
WARNING: 125
WARNING: 114
WARNING: 141
WARNING: 126
WARNING: 128
WARNING: 173
WARNING: 126
WARNING: 110
WARNING: 177
WARNING: 151
WARNING: 130
WARNING: 159
WARNING: 148
WARNING: 130
WARNING: 168
WARNING: 146
WARNING: 154
WARNING: 135
WARNING: 196
WARNING: 130
WARNING: 136
WARNING: 165
WARNING: 138
WARNING: 141
WARNING: 137
WARNING: 139
WARNING: 146
WARNING: 131
WARNING: 163
WARNING: 145
WARNING: 131
WARNING: 130
WARNING: 142
WARNING: 156
WARNING: 161
WARNING: 150
WARNING: 138
WARNING: 141
WARNING: 131
WARNING: 156
WARNING: 138
WARNING: 133
WARNING: 129
WARNING: 130
WARNING: 132
WARNING: 135
WARNING: 145
WARNING: 881
WARNING: 645
WARNING: 629
WARNING: 652
WARNING: 641
WARNING: 657
WARNING: 696
WARNING: 628
WARNING: 609
WARNING: 632
WARNING: 641
WARNING: 618
WARNING: 638
WARNING: 628
WARNING: 618
WARNING: 787
WARNING: 638
WARNING: 612
WARNING: 622
WARNING: 889
WARNING: 622
WARNING: 642
WARNING: 661
WARNING: 644
WARNING: 928
WARNING: 854
WARNING: 958
WARNING: 845
WARNING: 829
WARNING: 869
WARNING: 858
WARNING: 823
WARNING: 832
WARNING: 921
WARNING: 1031
WARNING: 844
WARNING: 696
WARNING: 640
WARNING: 751
WARNING: 842
WARNING: 662
WARNING: 672
WARNING: 652
WARNING: 670
WARNING: 653
WARNING: 636
WARNING: 897
WARNING: 212
WARNING: 143
WARNING: 140
WARNING: 139
WARNING: 132
WARNING: 141
WARNING: 151
WARNING: 159
WARNING: 208
WARNING: 137
```
At last, the patch changes the developer overlay to be openable in case of loading a multiplayer savegame that was played without cheats and replays in observermode before saving, as discovered in the course of F1100948 / #5624, see rP19558, rP19651.