Draft: Persuasion modal UI dehardcoding
Alright, I decided to try and take some small piece of UI and dehardcode it. It turned out quite doable even with my limited C++ and OpenMW codebase knowledge.
I'm not sure how much of this MR (if any) you'll be interested to accept in main, but I figured I could use it in my fork as I recompile OpenMW with march=native anyway
I am a proponent of incremental approach in porting UI piece by piece, and during that process errors and missing features from the original UI are inevitable. Because of that it's necessary to add a toggle in settings, between old and new UI, so it could be turned on and off easily in runtime. I think it's okay to keep ported UI less feature-full for now, all missing bells and whistles could be added later. Reimplementing UI presentation layer seems like tedious, but simple process, however I tried at the same time produce reusable widgets or templates (e.g. buttons, padding, etc)
Considering game logic layer behind the UI, one could argue what is desirable level of dehardcoding is. In case of Persuasion modal, it's already mostly portable to Lua, but I'm not convinced that it is a good idea. Rewriting all the game logic in pure Lua poses high risks of introducing bugs and inevitably will make code more brittle and expensive to maintain due to lack of static typing. It might be more pragmatic to just add some extensions points/interfaces to allow modders override logic on per-button basis than port everything to Lua. I think if we go the full "rewrite gameplay logic in Lua" route we must introduce unit tests which compare results of C++ based logic with rewritten in Lua. I attempted to write such test, but my knowledge of cmake is not enough to make test target access logic in openmw binary target (looks like e.g. dialogimplmanager must be first extracted into separate target before one can access it in tests)
So it seems to me that right approach (at least for now), would be to define some interface for underlying logic in Lua, which will redirect calls to C++ implementations, and at the same time will allow modders to override parts of it as they see fit.
As a sanity check of the UI and interfaces I've added a sample mod, which updates nested buttons of Persuasion modal with success probabilities, calculated by logic partially extracted from C++ to Lua.
Beside lack of tests, I think that main flaws, which should be addressed before possibly merging this, are issues with focusing and keyboard. There are several intertwined missing features in Lua UI APIs, which make adding keyboard navigation to the dialog quite troublesome. Firstly, focus from mouse and keyboard in lua widgets gets merged together, while in mygui they work separately. Secondly, there is no ability to focus widgets manually from lua, because of that you can't really bind keyPress event handlers to buttons in dialog. I've added a focus method for an Element, but my naive approach conflicts with validation preventing nested DelayedAction creation. (I can't create/update element and set focus on it at the same frame) Alternative solution would be to delay focus call until the next frame, but I haven't found a way to do so (timers don't work while dialog is paused) Given all the issues above, I didn't attempted fix the fact that hitting escape key exits main dialogue window too or trying to add gamepad support.