Rendering events

Archive of the old editing forum
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

So barebones functionality is done: https://github.com/jewalky/gzdoom/commits/gz_master2
Currently going to sleep, will conduct some extensive testing later. All that I know right now, is that Destroy() works correctly, OnDestroy() works correctly, DrawPickup() is ui and works correctly.
Not 100% sure all holes are plugged, not 100% sure the implementation is correct. Didn't test anonymous functions either. Did, but not thoroughly. They seem to work.
Didn't update any ZScript code except Thinker and Inventory.DrawPowerup. Will do once the system is more stable.

Method logic is kind of split between here and here.
Field logic is mostly in FScopeBarrier.
There's probably still place for generalization of everything, especially the duplicated 3 blocks that resolve Side_Virtual based on ctx.Function and ctx.Function->OwnerClass in codegen.cpp.
I really don't like the esoteric "need a writable value" message produced by the write check, going to try to somehow forward/print the actual message from FScopeBarrier which is way more informative and would say that <scope> <variable> can't be modified from <outer scope>.

How it currently works, in English:

Classes/structs:
1. Each class/struct can have either 'play' or 'ui' qualifiers. No qualifier means 'data'.
2. You can promote a 'data' class to either 'play' or 'ui' using inheritance, but can't change an already established 'play' or 'ui' class to another type.

Fields:
3. Each field can have either 'play' or 'ui' qualifiers. No qualifier means "inherit class/struct type", i.e. a default field in a 'play' class will have 'play' scope.
4. 'clearscope' on field is not allowed, because otherwise it would mean that you can create a data field in any object and pass anything around using that field.
5. In structs, 'play' and 'ui' is passed through member access chain, in a way similar to 'readonly'. That is, if plain data struct is declared as an 'ui' field, everything unspecified in it becomes 'ui'.

Methods:
6. Each method can have either 'play', 'ui', 'virtualscope' or 'clearscope'.
6.1. 'play' means the method can only be executed from 'play', and it's contents can't access 'ui'.
6.2. 'ui' means the method can only be executed from 'ui', and it's contents can't write to 'play'.
6.3. 'virtualscope' means the method will use whatever scope the self object is using, and it's contents will use the owning class scope (incl. inherited, that is, virtualscope OnDestroy in Actor will be 'play', but virtualscope OnDestroy in Object will be 'data'). Virtual scope is doublechecked: first during compilation (since it really can't do false positives, because 'data' is callable by anything and in no way the non-'data' type can change in child classes), then during runtime.
6.4. 'clearscope' means the method is 'data'; it will have readonly access to 'play' and no access to 'ui', but can be called from both.
7. Virtual method's scope qualifiers can't be changed (i.e. 'play' virtual method is 'play' forever).
8. Anonymous functions receive 'play' because these can only be in states anyway.
9. 'const' methods can be called from non-'play' on 'data' that belongs to 'play'.

Construction:
10. Same rules as for writing apply: mismatching scopes can't construct each other, but anything can construct 'data'.
ZzZombo
Posts: 315
Joined: Mon Jul 16, 2012 2:02 am

Re: Rendering events

Post by ZzZombo »

Why not go the same route I've seen in the DotA 2 scripting API? To send and receive messages/arbitrary data to/from the UI, you have to use the network event manager/define custom net tables that will hold the data and trigger updates in the UI.

Net tables in DotA 2 contain arbitrary complex data structures (no predefined structure), the payload, and have a name you refer to them under. They are capable of triggering an update event when any field's value changes, so you have to check manually what was updated, as they don't track changes down to each individual updated field.

Custom net messages are akin to net tables, but instead of being sent automatically when a value of inside a table changes, you have to manually trigger them. Their payload has to be specified each time you trigger one, and will be received by the other party.

Case #1, we want to read the player's health for the HUD: define a net table named 'players'. The game code writes here all player data relevant to UI, like name and health. The UI code reads the field 'health' of the table 'players' of the current player, and displays it somewhere somehow.
Case #2, we need to restart the level in case of mission failure, if the player agrees to it in a confirmation dialog, otherwise quit to the main menu. The dialog code sends a custom message 'failure_dialog' that contains the result of the choice, say, a boolean 'result' where true means restart the level, and the game code initiates the actual restart of the level or exiting to the menu accordingly.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

Case #1: you will have to redefine all level structures twice. Imagine if someone wants to draw the automap in the UI. Easier to just give it proper readonly access.
Either way what you said here is not about permission separation already, but a proper non-P2P networking engine.
What's good about this thing that I made is that it requires minimal modifications in the existing code to work.

Case #2: that's how it will be done, except not sure if I want to even try to send actual objects over the network. Currently network message consists of a string and 3 ints.
dpJudas
 
 
Posts: 3044
Joined: Sat May 28, 2016 1:01 pm

Re: Rendering events

Post by dpJudas »

As zzyzx mention, the idea here is to avoid forcing all communication to go through events. Doing it with events would been much easier to code engine-wise, but from the modders perspective creating events is a bit of a pain.

By making the playsim readonly from the UI you can always just grab health and other stuff directly from the structures, just like the renderer also does. That is a much nicer thing to do than "shit, my UI needs to print variable X now - I need to get an event firing it, then hook up a handler receiving it and then store it in a variable for the UI to print".

Sending data back to the playsim will have to be done through messages though. I could also imagine there are some cases where the preferred pattern is to fire an event from the playsim for the UI to receive.

@zzyzx: Keep up the good work - what you got so far listed in your earlier post looks very promising. If we can get this approach to work in ZScript I think we'll get something really nice.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49073
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Rendering events

Post by Graf Zahl »

dpJudas wrote: By making the playsim readonly from the UI you can always just grab health and other stuff directly from the structures, just like the renderer also does. That is a much nicer thing to do than "shit, my UI needs to print variable X now - I need to get an event firing it, then hook up a handler receiving it and then store it in a variable for the UI to print".

Sending data back to the playsim will have to be done through messages though.
And that's by no coincidence how the C++ code handles it.
dpJudas
 
 
Posts: 3044
Joined: Sat May 28, 2016 1:01 pm

Re: Rendering events

Post by dpJudas »

Graf Zahl wrote:And that's by no coincidence how the C++ code handles it.
Ah, that just makes it even more clear we are on the right track if we can get this to work. The power we have in the C++ implementation, with the readonly safety added to protect the modder. What is there not to like? :)
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

Right now, thanks to the idea of blocking any interaction with ui outside of ui, I have clearscope fields disabled. This means that anything inside a play class will always be play without any options. Is that really ok?
I for now think that at least picnum, alpha, renderstyle, angle/pitch/roll can be writable from ui, as well as there might be some non-ui fields in an ui class, and disabling clearscope prevents legit usages as well.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49073
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Rendering events

Post by Graf Zahl »

None of those fields may be writable, because they are used by the playsim, e.g. to determine visibility. But yes, play classes do have UI fields. Not necessarily actors, but sectors and playerinfo both have fields that do not belong to the playsim.
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: Rendering events

Post by ibm5155 »

uhh names...
what about internal ? where you get the data but cannot set it by the user, only the the internal code from engine can change it.
If I get it right, you guys're trying to do something like (in C#) int somedata {public get; private set;}
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

For that there is already internal keyword that overrides readonly (but only when used in ZScript lump #0, that is, gzdoom.pk3).
It's not exactly that.
User avatar
Nash
 
 
Posts: 17439
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Rendering events

Post by Nash »

After re-reading this discussion, what I understood was - there will never be a way to draw text or graphics to the screen at uncapped framerates.

I get the impression that even if the HUD object is scriptified, the actual drawing will be stuck at 35 Hz.

Someone please prove me wrong?
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

From what I understand, finishing the ui-play separation is enough for Graf to unblock per-frame callbacks.
I don't have time for shit though. Maybe on weekend.
User avatar
Nash
 
 
Posts: 17439
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Rendering events

Post by Nash »

When can RenderOverlay be enabled?
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49073
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Rendering events

Post by Graf Zahl »

When I have a plan how to handle the HUD.
If the render overlays get activated before that the ensuing mess is something I do not want to deal with. As it is implemented right now it circumvents absolutely everything in terms of user control over these things.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: Rendering events

Post by ZZYZX »

  1. People already abuse HUDMessages for weapons. That's no different really, and that's what you get when you limit people to only drawing on the HUD: people do non-HUD features using HUD.
  2. Still keeping RenderOverlay disabled is way overprotective now, especially after playsim protection was implemented.
  3. Also, what user control you are talking about with RenderOverlay? (just curious, never thought of anything like that...)

    I don't think there should be any generalized "user control" over something that directly draws and thus you can't predict what it will be used for. Especially if it's what I think it is, e.g. forcing some virtual resolution on it. Again, RenderOverlay is not solely for HUD and not solely for Doom HUD, and non-Doom TCs may as well want to not give user any control, if it's, like I made an example above, a Warcraft-like RTS interface, which in no circumstances can be scaled to 320x200.

    On the other side, if it's optional, i.e. the modder has the user settings and can choose if he wants to obey, then RenderOverlay should simply be moved to the proper place in the pipeline and the relevant settings stored in RenderEvent or OverlayEvent that can be inherited from RenderEvent.
Also, one unrelated thing, InputProcess should be 'ui' as well. I forgot to add the keyword there.
Last edited by ZZYZX on Sun Mar 05, 2017 6:45 pm, edited 1 time in total.
Locked

Return to “Editing (Archive)”