The Widgeting Paws of Pointerism (Notes on Graphics in Eulora, V)

August 6th, 2019 by Diana Coman

It took indeed more than a week and I'm rather surprised it didn't actually take even longer than two weeks to get *anything visible* out of it. It's all one strand like Stan's spittoon after all, so there's rarely just "one sip" that doesn't bring in the whole rot with it and I have to fight over and over the urge to just burn it all down and start a sane thing from scratch1. Nevertheless, a lot of deep breaths and assorted cussings later, here's a brief summary of the main achievements, in the order they were made:

  • some useless crap was removed and the whole thing made to work without (e.g. the doll with its dependence on a special sector in the map file);
  • the initial loading and "pre-caching" of meshes, textures, materials, maps and 2D stuff was excised (there are still the shaders remaining though as well as 1001 "preferences" in as many files in yet as many different places, sigh);
  • the actual handling of 2D icons and GUI images in general (e.g. buttons, borders, arrows, window decorations) aka the PAWS was dissected and exposed and roughly mapped as ugly as it is;
  • as recorded proof of breaking PAWS and because of its shameful lack of proper way to load images on actual demand, the whole thing has had a run with the stupidest "mouse pointer" available in there and otherwise with absolutely no 2D images at all for the very lulzy effect that it even looks better in some ways than with all of the various pieces of "art", here it is:
    That snot on the screen is the mouse pointer on the black background starting screen.

    That snot on the screen is the mouse pointer on the black background starting screen.

    PAWS's shame: the better-looking interface with no images whatsoever (clicking the invisible widgets still works!)

    PAWS's shame: the better-looking interface with no images whatsoever (clicking the invisible widgets still works!)

The path that led in the end to the above started with me looking - as initially planned - at how the character (as moving sprite) is handled or rather mishandled, consider: there is the CEL layer that supposedly provides on top of CS the sort of structures needed by games to store and manage the various entities and objects; PS however "uses" it in principle but in practice it still mainly does its own thing anyway (and by now I strongly suspect that this pattern is simply because nobody ever spends the time to understand what they use); specifically, the PS way is to have a pscelclient class that supposedly manages game entities on client side (shouldn't CEL have been enough for that, you ask? most probably yes but that'd have taken someone to figure out first exactly how it works and who has time for that!!); but then there is *also* a pscharapp class that handles the appearance of the character (apparently that's too low stuff for "management" to handle) and there is also a psclientchar that moves about equipped items because this is yet neither management nor appearance but absolutely something separate - though you'll be hard pressed to notice much separation in the code for all this theoretical separation; and to top it all, the inventory and doll views that precisely reflect character's appearance and equipped items are actually the domain of something else entirely - the PAWS; and the PAWS (which is supposedly so separate as to bother to be a plugin by itself) in fact messes about with pretty much anything and everything from the engine to shaders and textures and 2D images (which are still loaded as... textures, but those are textures-this not textures-that) and xml-defined maps and hardcoded paths to all sorts of files it expects - nay, demands - to be present and just-so and at-start but oh-so-configurable. At which point it became clear that the PAWS mess is indeed such a large part of the whole mess that I'll simply have to get to the bottom of it just in order to move further at all.

Looking at PAWS more closely revealed that it's meant to be a GUI system. This initially rather puzzled me because there IS in fact already another GUI system in there, one that PS uses/relies on as a dependency, namely CEGUI. Then again, the PS style is to "use" something by simply sitting on top of it and mushrooming a lot of managers with hardcoded paths and expectations that they know the whole possible world upfront so there should be no surprise at PAWS, which is precisely this sort of thing - it mushrooms widgets and pointers rather than something-else and pointers, that's about all the difference from all the other PS masterpieces.

Masterpiece aside, what IS this GUI system PAWS? As far as I can tell, it's a lot of widgets so well organised that there are no less than 3 methods "FindWidget" because the 1st one (defined in pawswidget) checks the current widget and its children only, the 2nd one (in pawsscript) checks also the parent of the current widget while yet the 3rd one (in pawsmanager because yes, of course there are all sorts of managers) simply delegates it all to "mainwidget" aka a sort of calling the 1st one from the top of the tree (but no, they couldn't possibly notice that it's meant to be a tree and there are well-known algorithms for searches in a tree). Anyways, the fun part with widgets is the way in which they are defined really as each widget has an .xml file (in data/gui) that supposedly defines appearance only (though more concretely it's about which elements it contains and on what position) and a .cpp file (in client/gui usually) that supposedly defines behaviour. The funny bit however is that both of those, for all their pretense of clear separation (they even are in totally different dirs, yes?), quite directly reference both one another's bits and pieces AND global, all-of-a-sudden-made-hardcoded parts: the appearance references by name other widgets (that it uses for specific roles and in specific places so it's not just a name really) and "resources" aka pre-loaded images; the behaviour code in turn has to reference various components of course. And in all this, apparently nobody noticed that before you can talk of behaviour and of appearance, there has to be somewhere a *structure and nature* of the thing that actually is the core and therefore the driver of everything else... Then again, what structure and nature and such silly notions, when the whole thing is bent on defining anything and everything by its current, temporary position or at best some role it might fulfill for a while2.

The widgeting PAWS further has all sorts of notions regarding appearances: there are "skins" and "styles" and "resources" and they are all both hardcoded and expected to be fully known upfront. The Great Paws knows not only all the world that is but also all the world that could possibly be (the world as it defines it is all nothing but labels anyway so it makes sense in a way). And it enforces this by whining and even wagging its finger at the user if it ever finds that a file with what it *knows* is the "right" name is missing from its expected place, quite literally giving orders to the user, as the message spit is this:

"ART ERROR: PawsTextureManager loaded the image %s which was missing from the imagelist.xml and was loaded on demand. Add the image there!"

I'll add to the above: and blow your nose and stand up straight and cut your nails shorter! Imagine that, being such a shitty user that the poor, poor PAWS had to actually load an image on demand (how degrading!!), you nasty user, you! And note that this "on demand" is anyway the sort of "you demand what I'm willing to do or no dice" not any sort of actual demand: it only means it deigned to look (because it had to use that image) in the *same place* it looked initially (when it tried to load everything that there should ever be) just because you are the sort of shit that failed to put the image there when it looked the first time, you know? What sort of user does such a thing to a poor piece of code, you tormenter, you, shame on you!!!

Before you get your hopes up that there is at least some sort of "loading on demand", bash those hopes one over the head: for one thing this "on demand" still relies on the predefined list of what there *can* ever be so that if you request a "resource" it doesn't know about than tough luck, it won't try to look for it, it's not that stupid to do something useful; for another thing, there is no way to actually call this on demand: it's just a way of doing rigidly the same thing but expecting a different result because meanwhile the world should have better come to its senses and fit the expectations already, what.

If the above sadness is not enough, add to it this significant bit: PAWS considers itself a plugin and as such entirely separated from the actual client and therefore unable to use whatever the rest of the client knows. Sure, in practice this separation "works" by means of the main client class simply passing pointers to PAWS on creation - why use CPP if not for pointerism, after all. Moreover, the added benefit of this separation is that PAWS also gets therefore to have its own set of repeated XML parsing of all sorts since it can't use the already-repeated XML parsing that the client anyway suffers from. And finally, it makes somehow perfect sense to "separate" the main client from the GUI system seeing how they both use the same graphics engine anyway and moreover the main client loads some images as textures while PAWS loads...well, some images as textures, yes. But they are not the same "class" of textures, so that's significant separation, see?

Besides deep red, I tell you what I further see: since I have no intention to pass even more pointers on or otherwise to force this "plugin" nonsense on everything just for the very specialness of PAWS, it's way more likely that the paws will be clipped more to size and therefore will take their place as yet another of the many classes inside the main client, possibly together with all the rest of very-special-plugins if need be (of course the dependencies are not that simple). I'm still pondering this, mainly because the idea is to touch as little as possible the code rather than as much as it takes to clean it (mainly because clean it won't be anyway). But one way or another, I will have to find some reasonable way to bring PAWS in line with the rest and have it go and load resources from wherever (and whenever) it is told to. This might even require more discussion in S.MG's boardroom but at the moment and as a result of all the adventure above, I have at least a much clearer idea as to what the 2D part is all about so there is therefore a point to even start the discussion from.

  1. While it might *seem* faster that way, it's not, nor does it really make sense if one calmly considers everything involved. Urges like this are simply focused on getting rid faster of the current set of problems and do not care nor stop one second to consider the alternative set of problems that are bought by such "solution". So yeah, urges make very poor guides, how surprising. 

  2. And no matter how much I try to *not* see it this way, it always is the case that the closer one gets to the "how things look" and therefore in this case to graphics, the more confusion and more monkeying there is. 

Comments feed: RSS 2.0

8 Responses to “The Widgeting Paws of Pointerism (Notes on Graphics in Eulora, V)”

  1. Diana Coman says:

    And I'll add here this gem that I still forgot to mention in all the above, directly from PS team (2012): "Due to the fact that the PlaneShift engine has been in development for years, unfortunately, it brings with itself some design faults which at the time allowed to speed up development but now are an hindrance and will require editing of the project source for deployment."

    A few years later, in 2017, the PS team goes on to add to the above: "Probably one of the mistakes we did was to start converting our code in UE without first trying to learn how the engine works, and how it should be used."

    And I didn't even *search* for those things!

  2. Yeah, I remember PAWS-related profanity sitting with Chet in her 8th floor apt in BsAs. I'd be reading printouts and she'd smoke and curse and smoke and curse.

  3. [...] At the beginning of the month, I continued the work on graphics but moved from the 3D issues to 2D, namely the user interface with all the different icons and images and various bits that are sometimes known as the "skin" of a client. This required a deep dive into yet another plugin of the legacy client, the widgeting PAWS. [...]

  4. [...] not working anymore! Why? Well, because it turned out that the client's controls relied on various PAWS widgets being loaded and those widgets relied on one another and on all sorts of graphics being present and [...]

  5. [...] my own expectations, it seems there's little resistance left even in that mess of paws: it took less than a week to map it all out quite fully this time, discard yet another set of dead [...]

  6. [...] except when they are overlays and otherwise they are made still on top of and with various bits of the paws that apparently would really, really want to be of some use, if only it hadn't been so thorougly [...]

  7. [...] above is the amazing result of trying to make use of all that psSlot and psSlotManager and pawsManager's drag-and-drop wonder and marvel of open source crowning achievement and glory. I ask the bloody [...]

  8. [...] effect the reset of the font's colour though! Such is the underlying nature of the inherited core widgets, this ever plentiful source of surprises of the most... surprising [...]

Leave a Reply