App Machine

One of my long time desires has been having an application that allows me to run script apps on my computer. Of course, two such applications exist for Javascript: NW.js (formerly Node Window) and Electron. However, I don’t particularly enjoy Javascript for some reason. I would like to write in Copper. So I created an application like NW.js, called Cauldron. Cauldron was made readily usable over a year ago, but I’ve been tinkering and toying with it. Let me spend time in this article running over my thoughts…

Read more: App Machine

Cauldron is a micro application runner that loads a .soup (zip) file containing Copper files for running an application. The .soup file can contain images too, useful for buttons. Cauldron uses Irrlicht to create a single window within which Copper can be used to add GUI elements and callbacks. Like NW.js, the main application instantiates the window, so their can only ever be one window, and its size features are either defaulted or must be set by command line option. This is slightly annoying if you’re trying to create a cool temporary loading screen, and totally useless if you’re creating an application that doesn’t need a window at all. Moreover, if you are creating an application that must be translated, you won’t be able to set the application-wide font that might be more suitable for other languages, so I had to include a special one for my purposes.

That said, I’ve been considering switching to an approach like Electron: having Copper be run as the main application and allow it to launch Irrlicht windows. The sad part is that much of the code I’ve written for Cauldron will need to be discarded, modified, or used for reference, particularly Copper Bridge.

Second, wouldn’t it be slow? One of my concerns with Copper is that it would be incredibly slow. This concern came after a test I did by having Copper do all the math necessary for calculating a mandelbrot. It required over a minute and a half for a 40,000 pixel image, which is slow. But to be fair, it took raw optimized C++ a full 10 seconds. I decided to run yet another test, this time on just setting the colors of 90,000 pixels. It ran in a second and a half, which is great news. It means that as long as Copper doesn’t need to do too many operations every cycle, it should be fast enough keep a main application loop at 60fps or more.

If I did write this kind of application, it would put Copper in the driver seat… and reveal all the areas that Copper is inept or lacking features. To be fair, Copper needs lots of help. Because it doesn’t create a compiled language, the Copper engine is more for data management: it can orchestrate the connections of a big application… just don’t ask it to do the tedious calculations. But at that rate, you might be wondering “why bother?”, after all, if you’re doing the bulk of the work in C++ those connections are faster to make in C++. The problem with C++ is that, the bigger the application becomes, the more tedious it is to modify, improve, and refactor, whereas with Copper, it’s easy.

Again, the downside is that specialized functions need to be written in C++, which may not have as much utility beyond certain specialized types of applications. For example, I have considered making an application for creating fractal flames with Copper, but this requires specialized functions – some of which must be threaded – that aren’t useful for anything but art applications. That said, rather than creating a generic do-everything-app-for-Copper-apps, I’ve considering creating applications that build on a framework of C++ and Copper. This framework I implemented and named Curri. The downside of such a framework is that I have to compile it every time I make changes on the C++ side (thus removing the advantage of using a scripting language), but I’m doing that anyways for Cauldron, so what does it matter?

GOOEY GUI Problem

Irrlicht is like a box of basic toys. It lacks many features, which you can extend, but only to some degree. The GUI system is very easy to extend. But adding other features, like the ability to remove window decorations or communicating with any dbus app (like Anthy – needed for inputting foreign language text) is a pain. Plus, its codebase is steadily going outdated, so it lacks OpenGL4 and Vulcan, but who cares.

It’s 2023, and so far, the options for GUI + 3D still stink. You can have one or the other, but not the best of both. The options for C++ GUI are GTKmm and Qt… and maybe Juce (if you can get it to work). Other GUIs either piggy back (e.g. wxWidgets) or lack features (e.g. Nana). Here’s a list.

GTK has plusses and minuses. It looks and feels nice; has support for Unicode and vector graphics using Cairo natively; has support for dbus Anthy; has support for stylus and other devices. But GTK3 – the common breed – lacks support for OpenGL, and doesn’t have any easy way to connect with Irrlicht nor OGRE. (I did manage to connect them using the software renderers in Irrlicht, but that’s not ideal). Furthermore, it’s a pain to add new GUI elements, and the codebase is a cryptic mess I’d rather not touch. Finally, it doesn’t support high-res screens, so GTK itself will become obsolete with increasing screen size.

Qt has all the features of GTK (except Cairo, which can be added) and isn’t hard to build on… but it has a HEFTY price tag, so you can’t build anything commercial with it. (Not really a problem for me: if I wanted to charge money, I could sell the Copper portion and give away the app engine for free.) But the ugly part is its build system: qmake… now cmake. cmake is a plague. If I wanted to avoid it, I guess I could write a huge premake script for Qt, but the issue is that Qt has always required some “pre-compile” settings and operations that can’t be simulated with premake.

And both GTK and Qt want to run their own loop and control the application. What framework doesn’t? Even Juce does that. That’s a problem if I want Copper to be in control of the main event loop.

In short, it looks easier to simply modify Irrlicht to accommodate my needs. An IME-like system (for inputting foreign text) wouldn’t be too hard to develop.

What about developing a GUI in Copper? I have toyed with this idea, but speed may be an issue, especially if Copper is called upon to control some minute details of render graphics. This could be avoided by having special classes for rendering, but these can start to get complicated or too specialized, and then it’s not much different than having the GUI in C++ anyways. On top of all this, it doesn’t solve the other problems like IME/Anthy, stylus or touch input, and a host of other things that have to be done on the lower level.

Concluding Thoughts

I have puzzled over this problem for awhile, and as the years go by, a new GUI solution has not arisen yet, so I’ve been stuck. It’s a monumental task to rewrite a GUI library. It would be nice if people provided cross-platform pieces like mouse/keyboard/touch input, widgets, icon loading, and finally main event loop instead of mashing it all together. I guess the downside of that is figuring out how to piece it all together, but this wouldn’t be so bad if people wrote readable code like the devs of Irrlicht.

On the bright side, I’ve been able to write and test Copper scripts using Cauldron for some time, so I’m able to create prototypes for interfaces to see what I’m planning before I commit anything to a pure C++ implementation.

If you’re interested in Cauldron, feel free to drop a comment. I haven’t released it yet because it’s always in development and knowing how to use it requires some info scattered between it and the Irrlicht code base (which I could document, but why when I’m the only one using it?), but maybe someone would like to try their luck at compiling and using it.

Leave a comment