[idea] "overriding OnPaint" in AGS GUI Buttons

Started by eri0o, Sun 14/04/2024 22:42:50

Previous topic - Next topic

eri0o

This is just an idea, basically I always do some things to theme buttons in my games

https://github.com/ericoporto/dont-give-up-the-cat/blob/fc2810d9d580f6e1b51742489fa388fbd96cdbd0/dont-give-up-the-cat/GameMenu.asc#L830-L874
https://github.com/ericoporto/i_rented_a_boat/blob/72740f53a9bce6f0790cc6191724354c5ae5a7b9/I_rented_a_boat/Menu.asc#L635-L675

The problem is I have to hold the dynamic sprites for each button state, and this also means I want to clean the dynamic sprites before saving and regenerating them after load (and save too), to avoid adding unnecessary data in the save games.

I was looking into the generation of texts with multiple colors, and if there was some way to override how buttons or labels were draw, it would be trivial to add support to them in GUIs.

Of course have zero idea how feasible this would be - in AGS terms, I believe the engine GUI stuff is in the common part with the editor so it would require some magic in the engine side to enable some way to override this, I imagine it would use something like the custom dialog stuff.

Crimson Wizard

Is not storing dynamic sprites in saves the main reason for this?
A while ago I proposed an option to not save particular components in save, by passing set of flags to SaveGameSlot.

eri0o

I think you still having to manage the lifetime of these dynamic sprites is a lot of work. A GUI could disappear to never be seen again in a game and you will keep the dynamic sprite in memory.

The other approach is to have better defaults like 9 piece support for drawing buttons and GUI backgrounds.

But still, drawing text can't easily be replaced by script - like it is possible in plugin - so can't figure a nice way to work with GUI elements. :/

Crimson Wizard

#3
Quote from: eri0o on Tue 16/04/2024 19:13:08I think you still having to manage the lifetime of these dynamic sprites is a lot of work. A GUI could disappear to never be seen again in a game and you will keep the dynamic sprite in memory.

GUIs are not exclusive to this problem. This is true for everything else, like when using dynamic sprites on overlays, or room objects, etc.
I suppose this problem may be more common for overlays, as they are temporary objects by nature.

Self-cleaning dynamic sprites may be achieved if there were a mechanism that connects a sprite to an object with reference counting.
Right now sprites are assigned as numbers. If they were assigned as pointers instead, then unassigning them from an object would release the dynamic sprites.
But, if a existing assignment of a sprite ID is kept, there still may be a system that counts assigned and unassigned numeric ID too, only done outside of the managed pool (because it can only count pointer references by script vm).
EDIT: tbh i'm not certain about this idea of counting assigned IDs, I thought about it once when investigating dynamic sprite updates, and it seems not fully reliable.

The thing about drawing callback, on the other hand, is that there has to be some drawing surface prepared for this anyway, associated with particular gui or control, and managed somehow (know when to allocate, and when to free). For the long term this has to be analyzed in regards to potential move to fully hardware accelerated guis (right now individual control looks are still drawn as bitmaps first), to see if it won't conflict with or prevent that.
Probably that "hardware-accelerated drawing" may be an important step to bring things to uniformity here.

Quote from: eri0o on Tue 16/04/2024 19:13:08But still, drawing text can't easily be replaced by script - like it is possible in plugin - so can't figure a nice way to work with GUI elements.

If you are referring to "font renderer" interface, then, again, this problem is not exclusive to GUIs, there are multiple things a text may be drawn on. It would be also nice to have this issue solved consistently, independent to what the text is drawn for.

eri0o

Quote from: Crimson Wizard on Tue 16/04/2024 20:48:18GUIs are not exclusive to this problem. This is true for everything else, like when using dynamic sprites on overlays, or room objects, etc

I think overlays aren't because they have the clone option which you let it clone and then you don't need to have the dynamic sprite in the global state. You can actually bypass putting the overlay itself in global state if you just want to quickly show it by using a Wait, which will delay the overlay reference being collected only once the scope is over - after the wait.

Crimson Wizard

#5
Quote from: eri0o on Tue 16/04/2024 22:47:44I think overlays aren't because they have the clone option which you let it clone and then you don't need to have the dynamic sprite in the global state. You can actually bypass putting the overlay itself in global state if you just want to quickly show it by using a Wait, which will delay the overlay reference being collected only once the scope is over - after the wait.

This is just a specific use case of overlay. In a similar case, if you display GUI only for a moment with Wait, you may clean the dynamic sprite up after that.

"Clone" flag indeed makes it easier, but it is there only for backwards compatibility, it would not be there otherwise (and frankly I think it should not be there, as it makes them inconsistent with other game objects).

Crimson Wizard

I think, technically, this kind of callbacks are possible, just like they are possible for custom rendering of dialog options. This may be done as an experiment.

My main concern is what kind of dependency this will add to the game rendering.

Another thing is, I feel like at least some of the issues mentioned here as reasons for this callback should rather have different solutions.

eri0o

I don't think the callback is a good idea in itself, I also have no idea how to implement such a thing - not in code, I mean in terms of design.

Like, for instance, a GUI control has an OnClick event, would one add an OnPaint event? This would mean that things I want to repaint I would fill this event - which in the callback would pass the control it's replacing. Now if a GUI doesn't have this I just don't add this in the event panel in the editor.

Not too sure on this though...

The other thing is perhaps at this point it's better to just do nothing until at some point more work can be done in speeding up drawing - this one is a bit hard, I could imagine doing this from ground up but adapting the existing drawing surface and keeping compatibility is not trivial. If this is fast perhaps implementing full GUIs in script isn't that heavy - like my ImGi module.

I've just recently tried to take a look in how the situation is currently to slowly replace/customize the AGS in light of looking the request for multiple colors in strings and it's amazing how I can only think that it's usually not possible and one has to reimplement very large parts of AGS because they are not very cistomizeable - I mean they are through scripting, but you need to script enough to replace a much larger part than the one you wanted at first. :/

SMF spam blocked by CleanTalk