mikke89 on master
Update readme.md (compare)
mikke89 on backends_refactor
Update comments (compare)
mikke89 on backends_refactor
Move the global shortcut handle… (compare)
mikke89 on backends_refactor
Add DL libraries to CMake Format SFML Start refactoring SFML/GL2 back… and 2 more (compare)
backends
branch, which will be merged to master soon: https://github.com/mikke89/RmlUi/tree/backends/Backends
Hello again, @mikke89
Last night I tried to use the code from backends
branch for a few hours and here is my feedback on it (I understand it's not finished yet, but anyway):
sf::Window
object. Apart from the fact that I want to use my own window (and even worse, what if I want 2?), the problem is that upon initialization this Window calls some OpenGL functions, which rely on other static objects. As we know from the C++ standard, the order of initialization of static objects is not defined (and is very unpredictable), and in my case the constructor of this Window crashed the program before it even got to main().Conclusion: Currently I'm very inclined to stay with the code from the old SFML sample. The only significant difference (that I could see) was the renderer implementation (though I don't know enough about OpenGL to notice the practical difference, because the old one also seems to work fine). And apart from that it's just very understandable. Create the SFML system interface, create the SFML renderer, point them to your window, and you're good to go. There is currently no advantage to upgrading (for me at least).
Sorry for being harsh but I hope you find this useful :)
It's not that singletons are an antipattern in and of themselves, but IMO they should only be used in two cases:
And whatever you do, don't make singletons depend on each other. There is no defined (de)initialization order. I learned this the hard way.
@jbatnozic Thanks a ton for the feedback. As far as I know you are the first one to take a solid look and trying to implement it into your own project. The fresh set of eyes is very valuable. Keep in mind though, I'm just trying my best here. Nothing is set in stone yet, and it's still early days with very few comments and documentation. I'm interested in taking this feedback and trying to figure out a constructive way forward.
sf::Window
object, I didn't know that the window had any heavy initialization. The OpenWindow function was meant to be completely optional and mainly for something quick and easy to get going, and as a place to put common code needed for our samples. Maybe we want to move it entirely into the backend. I'll certainly add a way to hand a pointer to any user window, and I'll happily take any specific suggestions.Thanks again for your feedback, and I want to say that I absolutely agree with your assessment: "I just want RmlUi to be 'plugged in' into my existing architecture". Yes! I'm totally on board with that, and that is my goal too. If you tried to copy out the GL shell and native platforms previously, that was a horrendous task. The SFML sample previously was in a different place because it was completely self-contained. This makes it a bit simpler, but it's obviously not sustainable to do this for every sample and backend combined. In some sense I want to be able to make all the other backends just as easy as the SFML sample was and if possible even more-so. And making it re-usable means we all benefit with improvements. I hope we can get there with more iterations and more feedback.
There are a lot of questions here but I'd like to start with this particular one:
Do you have suggestions for how to store the state of the backend?
I'd expect to be resposible for the lifetime of the backend myself. What I mean by that, is that I'd instantiate a Backend object of some kind, and then it would contain the System interface, Backend interface input converters etc.
getRenderer()
and getSystemInterface()
and probably a few more functions to set viewport and similar (not sure about this). You could provide some convenience functions together with it, like for converting between SFML events and RmlUi inputs and such operations, but IMO it's okay to leave them a little DIY. Instead of RmlUiSFML::HandleEvent(const sf::Event& event);
you could have RmlUiSFML::HandleEvent(Rml::Context& context, const sf::Event& event);
and since the user has their own loop and window etc. (but also provides his own Rml::Context) he should know when to call this.Thanks, that is some great feedback. I'm having many ideas based on your suggestions.
That main loop example is something I wrote on how I expect people to actually implement it in their own project. And you're right, this example would be nice to replicate in the samples. It's not trivial though since there is added complexity due to the necessary abstraction of all the different backends. But I do agree with you that we should be able to get closer to that example, I probably made some wrong abstraction levels here. I guess it's also okay to duplicate more code between the samples.
By the way, my initial idea was that the backend code (the actual glue code between renderer and platform) is something you would copy-and-paste into your own project, and sort of transform that into something like the main loop example. I see now that this backend code is a bit too fragmented to make that a trivial task, it takes more effort than say the old SFML sample. But perhaps if we make a better abstraction level we could have people re-use the backend as well.
I'll try to make some improvements and play around with the abstraction level. It would be great if we could follow up when I have more to show. Thanks again, your feedback is very much appreciated.
On an unrelated note, this page (https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/documents.html) mentions an "instancer" a few times, so I wanted to ask, is it a typo and is meant to be an "instance" (which would make sense in those sentences), or is an "instancer" a real thing in RmlUi and I just missed what it is?
Instancer is correct here, it is talking about element instancers for custom elements, you can read more about it here: https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/custom_elements.html#creating-a-custom-element-instancer
It would be great if we could follow up when I have more to show.
Don't worry, I'll stick around. I also need this to work for my own needs so I'll be glad to help.
It's a small market for C/C++ GUI libraries, and of those: some are archaic or not developed anymore at all, some are ugly and intended only for tools development, some have a hell of dependencies and are impossible to integrate, and some are simply too underdeveloped to be flexible enough. Noesis looks great but requires a licence, and ultimately RmlUi (What does Rml stand for anyway?) was the only one I found that had none of those problems. And as a bonus treat there was a Conan package for it as well so setting up took only minutes :D
Sounds good!
Yeah, it seems that this library hits this sweet spot for many people. I can resonate with that description of yours, I also ended up here after doing some research. At the time it was libRocket, which had already stopped being developed at the time so I started implementing my own fixes and desired features. Then the fork started gaining popularity and here we are. Rml stands for Rml Markup Language :P
Hello there !
Saw this library a while ago and thought "hey, it's pretty interesting"
Realized today after reading this post https://www.reddit.com/r/cpp/comments/uv3cqd/is_there_any_mitbsd_licensed_ui_framework_for_c/ that RmlUi supports SFML and Lua integration, it's awesome !
https://tgui.eu/ is also a good solution for my needs but being able to leverage HTML for making an UI and scripting with Lua sure seems appealing :)
(It's for a game engine ui btw)
@mikke89
Ultimately I ended up making my own SFML backend, based on what I believe is a reasonable API for users. And because it was such a nice, small, self-contained example I put it up on GitHub so maybe it gives you some inspiration for your backends. <link>.
(note: "SPeMPE" is the name of a larger project where I plan to move this and that's the reason why everything is under that namespace.)
Hey. I've made some efforts to cleanup the backend interface and in particular the SFML/GL2 backend. See the loaddocument sample, the backend interface, and the SFML/GL2 backend, plus the underlying renderer and platform.
Here are the main changes and rationale behind them:
main()
:) Calls to the backend are now always done from the sample code, while the shell merely acts as common functionality for the built-in samples that is most likely not needed for other users.Let me know what you think about this direction :)