Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate RmlUi #1415

Merged
merged 121 commits into from
Sep 1, 2024
Merged

Integrate RmlUi #1415

merged 121 commits into from
Sep 1, 2024

Conversation

p2004a
Copy link
Collaborator

@p2004a p2004a commented Apr 6, 2024

Main RmlUi integration PR into engine. It is replacing #1076 and #1304.

To contribute to this work, please open separate PRs with clean git history into https://github.com/beyond-all-reason/spring/tree/rmlui-integration branch.

The branch is rebased on top of the stable BAR engine release version.

We will be periodically making Game Dev facing preview builds, and those are available in BAR launcher as "Engine RmlUi", latest: https://github.com/beyond-all-reason/spring/releases/tag/rmlui-integration-preview-v5

so they can test functionality and API before it fully lands into engine.


This description will be rewritten focusing on the summary of changes when we get close to merging.

@p2004a p2004a mentioned this pull request Apr 6, 2024
RmlGuard = true

-- Load fonts
RmlUi.LoadFontFace("Fonts/FreeMonoBold.ttf", true)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if a game doesn't do this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly do not know for this one, I'll try commenting it out and get back to you.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/fonts.html :

TrueType and OpenType fonts can be loaded into RmlUi by the application. RmlUi has no default font, so at least one font must be loaded before text can be rendered.

I have just tried commenting out the font loading in my own code, and:

  • Text is no longer rendered.
  • RmlUi logs warnings and complains about no font face being defined.
  • Buttons and the rest of the UI works, at least in my own project.
  • If you are running with the debugger (Rml::Debugger::Initialise()) , RmlUi loads its own "rmlui-debugger-font" to show debug text in the debug UI element inside your application window.

RmlUi describes "fallback fonts" in https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/fonts.html . So if the RmlUi integration code defines at least one fallback font, unless fonts can be unloaded, text will as far as I can tell always be rendered (except for the characters that the fallback font does not include). You can also define multiple fallback fonts.

]]

-- when "cursor: normal" is set via RCSS, "cursornormal" will be sent to the engine
RmlUi.SetMouseCursorAlias("default", 'cursornormal')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if a game doesn't do this?

Copy link
Member

@ChrisFloofyKitsune ChrisFloofyKitsune Apr 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the .rcss files will have to specify the game specific cursor name to use

instead of

.example {
    cursor: default
}

they would have to put

.example {
    cursor: cursornormal
}

the latter of which makes css parsers/style checkers confused and css code in general less importable if it was developed elsewhere

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also comment says "cursor: normal", shouldn't it be "cursor: default"?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of

.example {
    cursor: default
}

they would have to put

.example {
    cursor: cursornormal
}

what if they put default there regardless?

Or, say my widget wants the "wait" cursor (hourglass). since this file doesn't set it, will that fail?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as if any other part of the code that tries to use a cursor that's not registered with the engine-
it will default to "" in the MouseHandler code

void CMouseHandler::SetCursor(const std::string& cmdName, const bool forceRebind)
{
if ((activeCursorName == cmdName) && !forceRebind)
return;
const auto it = cursorCommandMap.find(activeCursorName = cmdName);
if (it != cursorCommandMap.end()) {
activeCursorIdx = it->second;
} else {
activeCursorIdx = cursorCommandMap[""];
}
if (!hardwareCursor || hideCursor)
return;
if ((hwHideCursor = !loadedCursors[activeCursorIdx].IsHWValid())) {
SDL_ShowCursor(SDL_DISABLE);
mouseInput->SetWMMouseCursor(nullptr);
} else {
loadedCursors[activeCursorIdx].BindHwCursor(); // calls SDL_ShowCursor(SDL_ENABLE);
}
}

which is assigned here in the init/reload code

AssignMouseCursor("", "cursornormal", mTopLeft, false);
AssignMouseCursor("Area attack", "cursorareaattack", mCenter, false);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if every command defaults to "" if missing, and "" command is assigned the "cursornormal" cursors in engine, then does RmlUi.SetMouseCursorAlias("default", 'cursornormal') actually do anything?

a rml widget will say .example { cursor: default }, this will fallback to "" because "default" is missing, and "" uses "cursornormal" anyway, no?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the worst case outcome of this? If the worst case outcome is fairly minor, it would be fine to improve this, but not something that should block the PR, in my perspective at least.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My aim is to

  • see if it would be possible to get rid of this file
  • become aware of the caveats etc for documentation purposes if not

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the version of this file I have in my rmlui-example-widgets branch has a lot more going on
I stripped down that file to make this one

https://github.com/ChrisFloofyKitsune/Beyond-All-Reason/blob/rmlui-example-widgets/luaui/rml_setup.lua

in terms of useful stuff, 4 fonts are loaded and 5 cursor aliases are set there

@@ -674,6 +706,13 @@ std::string CMouseHandler::GetCurrentTooltip() const

void CMouseHandler::Update()
{
// Rml is very polite about asking for changes to the cursor
// so let's make sure it's not ignored!
if (RmlGui::IsMouseInteractingWith())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could use brackets for multiline contents

#undef cast
#undef registry
#endif
#include "lib/lua/mask_lua_macros.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a standalone PR to get it out of the way

@@ -59,7 +59,7 @@ static void ExitSpringProcess(const char* msg, const char* caption, unsigned int

static void ExitSpringProcess(const char* msg, const char* caption, unsigned int flags)
{
LOG_L(L_ERROR, "[%s] errorMsg=\"%s\" msgCaption=\"%s\" mainThread=%d", __func__, msg, caption, Threading::IsMainThread());
LOG_L(L_FATAL, "[%s] errorMsg=\"%s\" msgCaption=\"%s\" mainThread=%d", __func__, msg, caption, Threading::IsMainThread());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be a standalone PR

@p2004a p2004a mentioned this pull request Apr 6, 2024
@@ -363,6 +363,23 @@ extern DECLSPEC void SDLCALL SDL_StartTextInput(void) {
extern DECLSPEC void SDLCALL SDL_StopTextInput(void) {
}

extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool capture) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could be a standalone change? idk

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this PR contains the first code that actually needs those extern stubs

Copy link
Collaborator

@sprunk sprunk Apr 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright, but i think it would be decent to get them out of the way regardless. the less of a monolith we have to review the better

@@ -9146,7 +9146,7 @@ namespace sol {

inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
const char* err = message.size() == 0
? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s")
? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s%s")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be a standalone fix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change to sol2 has been merged into upstream
we can just use the git submodule now instead of keeping a vendored copy

@blaisemccourtney
Copy link

In case it is of help to anyone, RmlUi's main documentation: https://mikke89.github.io/RmlUiDoc/ .


Rml::Initialise();

Rml::LoadFontFace("fonts/FreeSansBold.otf", true);
Copy link

@blaisemccourtney blaisemccourtney Apr 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Is the code supposed to load two different fonts? It also loads RmlUi.LoadFontFace("Fonts/FreeMonoBold.ttf", true) in cont/LuaUI/rml_setup.lua . Please disregard if intended (or maybe add a comment if you want).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot that this font was already loaded when I stripped down this file

https://github.com/ChrisFloofyKitsune/Beyond-All-Reason/blob/rmlui-example-widgets/luaui/rml_setup.lua

to make an example rml setup lua stuff for this repo

@ChrisFloofyKitsune
Copy link
Member

PR to clean up whitespaces

@ChrisFloofyKitsune
Copy link
Member

PR to push forward the "this could be a standalone change" stuff

@ChrisFloofyKitsune
Copy link
Member

Note that this needs done:

Implement the RmlUi font interface

https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/interfaces/font_engine.html
This will allow the RmlUI library to not link to FreeType as a dependency

@blaisemccourtney
Copy link

What does BAR usually use to draw text with? Or does it use its own internal FreeType dependency?

For anyone looking at implenting the RmlUi font interface, there are some samples for implementing a Rml::FontEngineInterface in RmlUi's repository:

RmlUi's default implementation for font handling, including FreeType: https://github.com/mikke89/RmlUi/tree/559d84ab274b8e480d9106f17602d439bf759b0e/Source/Core/FontEngineDefault .

@ChrisFloofyKitsune
Copy link
Member

What does BAR usually use to draw text with? Or does it use its own internal FreeType dependency?

... <snip>

BAR uses it's own FreeType dependency
Thank you for the links, I'll probably be needing those later

@ChrisFloofyKitsune
Copy link
Member

another batch of clean up changes and a bugfix

@p2004a p2004a force-pushed the rmlui-integration branch from 1afff6f to a8ff4b2 Compare August 30, 2024 18:43
@lhog lhog merged commit b260645 into BAR105 Sep 1, 2024
2 checks passed
github-actions bot pushed a commit that referenced this pull request Sep 2, 2024
* Add RmlUi to build system

Not all is ready and there will be more work needed on build system, but
the basic integration of RmlUi Core is done.

- I've not created and linked any of the provided GL3 or SDL backends,
  that needs separate work
- Lua bindings are blocked on mikke89/RmlUi#302
  we need to find some workaround for that
- Tracy integration is blocked on mikke89/RmlUi#516

* render first light

* remove sdl2_image

* VFS system integration

* rmlui lua and sdl integration

* rmlui reload support and better luaui integration

* delete extra file

* Temporarily switch to RmlUi branch with tracy integration fixed

* data model change detection bad edition

* fix for chobby support, better binds, translation table

* key event handling, luaui reloading, rmlsol bug fixes

* remove rml demo files

* create contexts lua side

* clean up comments

* allow multiple rmlui contexts

* pull out inner loop of processevent calls

* add comment to make it clear certain events are not captured

* Update RmlUi to latest git version

* headless building and lua support

* add lunasvg submodule

* update lunasvg version

* reset build option

* didnt need to build lunasvg as a shared lib

* fix: uint is not standard and breaks mingw compile

* Rework RmlSolLua integration into build

This fixes the build under mingw that didn't work because of broken
linking.

- Cleanup messu include_target_directories replacing with proper
  linking of targets. Had to fix the include target directories for
  lua lib
- Undo merging of the public and private interfaces, and separate
  public interface of the library
- Stop appending the include dir directly to engine include dirs
  and stop using absolute path based references when referencing.

* Fix RmlSolLua compilation under MSVC

- Designated initializers are C++20 feature, so we need to bump
  to that version
- Element.cpp generates huge amount of sections, so adding /bigobj
  switch for it.

* Document the mouse press check

* Change size() < 1 to empty. Move setActive after processContext loop

* Deeper MouseHandler integration for processing mouse events

* Fix software rendered mouse cursor

* Missed half of the move of this comment

* make lua binding for RemoveContext

* do less bullying of the RmlSolLua lib
instead set up our own plugin to keep track of created/removed contexts

* attempt to add thread safety to RmlGui::data->context accesses
allow RmlUI to properly set cursors
have RmlUI input events take precedence after other inputs (but after regular Lua input)

* have RmlGui store what cursor it would like (or "" to cede control of it) and have the system check that.
rename own custom Platform_SDL stuff to Platform_RTS
clean up code here and there, undo changes to random files

* Platform_RTS ended up being disliked, so re-renamed stuff to "RmlSystemInterface" and the namespace to "RmlSDLSpring"

* check Rml input first

* fix a singular character to be lowercase blargh

* fix spelling

* reference fix

* use cbitmap texture binding

* spaces to tabs with clang-format

* mask lua macros

* Remove unused variable

* add an explicit removeLua call

* accurate tracking of lua added items

* move general Rml::Context watching plugin outside of Lua init/destroy
get rid of never-going-to-be-used code in RmlUi_Renderer_GL3
rename file/class to RmlUi_Renderer_GL3_Spring since it's now more deeply integrated with Spring
move VFSInterface to own files

* left some mess in, sorry

* Remove unnecessary includes

* create new <texture> element which hooks into the existing LuaOpenGL/Texture code to be able to reuse already made textures

* what if we just kept the texture handle away from Rml

* clearer and more readable element tag name

* misc changes

- remove lua mentions in rml code
- initial insertion of lua work from loveridge/rmlui-integration-fork
- use translation table

* copyright auto insert go brrr too hard

* leave a note on the UI reload

* move RmlSolLua out of the lib folder so that it can integrate more with the rest of the Spring engine

* according to a tutorial, the proper implementation of the iterator concept looks like this

* minor cleanup

* minor cleanup as I investigate how Data Models work

* use the configured lua_Number type instead of blindly assuming double

* beginning refactor of RenderInterface

* we can just use `glPush/PopAttrib()` here

* narrow down to just the attrib bits needed

* misc changes

- give RmlUi lib code a double instead of a float for system time since that's what it's asking for
  make use of the Rml DataModel stricter
- (disallow adding keys to an existing DataModel)

* drop element render hook

* untested custom Rml Decorator: 'lua-render' (name not final)

* rml lua-render decorator barely functional
use like so <div style="decorator: lua-render(callback_name_here)"/>

* remove redundant Log binding from SolLua
Get the Rml_MathTypes_Conversions.h working

* many changes

* Actually add submodules

* Fix g++ compilation

* just use one shader program, copy in documentation comments to make working on the render interface easier

* SolLua  binding "low hanging fruit" cleanup

* make all the RmlUi Lua bindings into a "RmlUi" namespace table to better the other lua bindings
add setup files to cont folder

* add Mouse Cursor Aliases feature

* use <texture> instead of <lua-texture> as LuaTextureElement tag name

* add mouse cursor alias stuff to example rml_setup.lua

* touch up rml_setup.lua

* without the render_interface being 100% finalized, it is too early for DecoratorLuaRender to exist (made fork that still has it though)

* get rid of extraneous whitespace changes

* replace space indenting with tab indenting

* RmlGui::Initialize gets own globals + allow Reload to init

* clean up/fixing of init/shutdown/Context removal

remove SDLWindow/Context ref since they are not used in the end
keep Rml Interfaces alive until after Rml::Shutdown is called()
defer removal of Rml::Context objects,
this allows for the removal of the guarding mutex

* tidy event handling + more

include context removal in #ifndef HEADLESS
comment on why Update() is ran in RemoveLua()

* Replace README.md with notice of where the code came from

* Add MIT license info to almost all Rml/SolLua source files

* add support for border-radius property to ElementLuaTexture.cpp

* recalc geometry when rect attribute is set to (blank)

* create lua hook for the RmlUi debugger

* context ordering, rm PasThrPlugin, data > state

Allow changing the order of contexts in the state->contexts vector
clicked context is brought to front, but debug context (if exists) is always at the very front

PassThroughPlugin was a redundant abstraction

BackendState sounds better now that it's a class and not a struct

* fix debugger use-after-free crash

* remove contexts last in update

* fix crash in StyleProxy iteration

* add returns from element hierarchy manip bindings

* code style tidying

* allow nil and blank strings to clear a property

* Fix whitespace

* Remove lua mask/restore macros as fix is on BAR105

* bump to rmlui repo latest

* use renamed RMLUI_ option

* use new RmlUi target names

* Create Uniform*v variants that take a "count" parameter

* Initial update to RmlUi 6. Code is compiling.

* interface with Shader API correctly

* better init logging

* update "is initialized" check

* code/formatting cleanup

* sidestep the RmlUi resource handling to render the texture and geometry directly

* remove outdated comment

* fix use-after-free issue by removing debugger before shutting down lua

* size of a non-table is 0 actually

* RmlUi log pretty useful actually

* Don't deactivate the shader if TexturePostprocess is used

* ensure that RmlUi can be loaded after changing UI Size option

* bump RmlUi for flexbox gap feature

* inline rgba Colour binding macro

* remove outdated commented-out code

* update headless render interface stub

* (whitespace) correct accidental tab

* update RmlUi to official 6.0 release

* update backend files with updates made to the originals

---------

Co-authored-by: loveridge <[email protected]>
Co-authored-by: sprunk <[email protected]>
Co-authored-by: ChrisClark13 <[email protected]>
Co-authored-by: LHoG <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants