View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0006164 | The Dark Mod | GUI | public | 14.11.2022 21:07 | 14.11.2024 22:30 |
Reporter | stgatilov | Assigned To | stgatilov | ||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | feedback | Resolution | open | ||
Product Version | TDM 2.11 | ||||
Target Version | TDM 2.13 | ||||
Summary | 0006164: New features in GUI engine | ||||
Description | Perhaps add the following to GUI engine: 1) runScript command --- code is already here, just fix it. 2) namedEvent command: triggers named event with given name (exists on other idTech4 games). 3) Add "vec4" keyword as synonym for "definevec4", deduplicate code for "float" and "definefloat". Discussed here: https://forums.thedarkmod.com/index.php?/topic/21642-feedback-on-wiki-gui-scripting-language-series | ||||
Additional Information | https://forums.thedarkmod.com/index.php?/topic/22239-gui-features-runscript-and-namedevent/ | ||||
Tags | No tags attached. | ||||
For completeness, should probably also allow the form (reportedly widely used by id Software at one time): set "cmd" runscript <function_name>; (I'm not sure about where double quotes are needed here) |
|
Here is an example of how runScript command works in Doom 3 / TDM (it should work in 2.11 too). First, define a global function. For instance, I added to tdm_player.script: void testfunc() { sys.println("It works!\n"); } Then add somewhere in GUI script the call. For instance, I added it in readable.guicode in onAction handler: runScript "testfunc"; When I click Attack when reading a readable, this script function is triggered and I see the message in console. ----------------------------------------------- Here is how it works internally. runScript is a separate type of command, which accepts one string argument ARG --- which function to call. Whenever GUI script executes this command, it pushes "runScript ARG" command into idWindow::cmd (see Script_RunScript). Then at some moment someone pulls these commands from all windows. In my particular case, it happens in idPlayer::Weapon_GUI --- see the call to idEntity::HandleGuiCommands there. At this moment it sees runScript command and tries to find script function with ARG name. The name may contain "::", but as long as the function is found, it is called with no arguments. So you cannot invoke object methods like this --- only freestanding functions. I'm not sure game scripts support something like C++ static methods... but if they do, you should be able to call them as well. |
|
I think the real problem is that HandleGuiCommands is only executed in one code location, and only if player clicks "Attack" on this very frame. It turns out I was just lucky to write test code exactly in the only place where it works =) It is obvious that the system of passing commands from GUI was not intended as something that just does whatever is said immediately. It was instead designed as something that caller may act on if he wants. It was not intended that all commands are queued up until someone pulls them. Instead, they are stored immediately, and freely cleared between actions. So whenever someone calls idUserInterface::HandleEvent, it executes some GUI scripts inside, and might return a sequence of commands to the caller. That's what happens when player clicks Attack while interacting with GUI, but it is context-sensitive: some other action on the GUI might have no handling of the commands, or even different handling. Of course, if you call runScript in onTime handler, it probably won't do anything, because no one is looking at the resulting commands from them. The issue I see right now is that script can call GUI event via Event_CallGui. It internally calls idUserInterface::HandleNamedEvent, which does not return the commands (they are just gone). I think I can extend this so that returned commands are bubbled up to Event_CallGui, which schedules script calls in the future. However, anything else is context-sensitive --- that's by design. |
|
r10460 Cleaned up commands chaining on runScript GUI command + reduced error for unknown script function to warning. r10461 Merged definefloat and float, added vec4 keyword. Regarding "vec4", I check that it works with attached hacky patch =) "float"s is already used e.g. for lightgem crouch display. vec4_in_gui_hacky_background (897 bytes)
--- C:/Users/GATILO~1/AppData/Local/Temp/mainmenu_background.gui-revBASE.svn003.tmp.gui �� ��� 8 15:00:31 2021 +++ G:/TheDarkMod/darkmod/guis/mainmenu_background.gui �� ��� 5 21:09:17 2023 @@ -74,9 +74,21 @@ windowDef MainMenuBackgroundSwirly background "guis/assets/mainmenu/swirl" BACKGROUND_DEFAULT_BEHAVIOR(MainMenuBackgroundSwirly) + } +windowDef MyTimer +{ + vec4 MYCOLOR 1, 1, 0.5 + 0.5 * sinTable[time * 0.001], 0.5 + notime 0 + onTime 10 + { + set "MainMenuBackgroundSwirly::backcolor" "$MYCOLOR"; + resetTime 0 + } +} + // Background Figures windowDef MainMenuBackgroundFigures { @@ -324,7 +336,7 @@ windowDef FailureBackgroundOuterdirt windowDef MainMenuBackgroundOverlay { rect 0, 0, 640, 480 - matcolor 1 ,1 ,1 ,0.6 + matcolor 1, 1, 1, 0.6 background "guis/assets/mainmenu/background" BACKGROUND_DEFAULT_BEHAVIOR(MainMenuBackgroundOverlay) |
|
There are several things to decide here. 1) Regarding "namedEvent" in GUI: how does it work in games where it exists? Does it trigger the event with this name on current window only, or on all windows in the UI? Does it trigger event immediately (unlikely), or does it schedule execution until the script handler is over? Maybe it works via the same window cmd system as runScript command? 2) Regarding runScript. What use cases do we want for this feature? Looking at specific examples, we can decide how to adjust the current architecture... |
|
It's been a year since I've thought about gui scripting. Let me start with runScript, and how I should change my wiki entry to more correctly express its *current* capabilities (as of 2.11). I understand the call can only be used effectively within an onAction handler. Some questions: Can the global function called be in any .script file, or only in the map_name.script file (invoked with or without "map_name::" prefix)? Can that function have a loop (perhaps containing a wait), or must it be executed and completed in 1 frame? HMart said that another way it could be used is as the name of a placeholder spawnarg (like gui::gui_parm6) on the attached entity, that has the function name, e.g.: runScript "gui::gui_parm6"; True? |
|
Also, thanks for "vec4" keyword. I will change wiki to say it's forthcoming in 2.12 | |
Yes, if you have a GUI, you can put it into "onAction" handler of some window/button so that it gets executed on LMB click. The global function can be anywhere, files don't matter at all for script I believe. The script function is executed in a new script-thread, so there is no problem if it would wait/take time. As for putting function name into gui parameter, I think it should work due to how GUI scripting works in general. |
|
OK. Other questions are - - does runScript have to be the last statement in an onAction event block? - if not, can two calls be in separate arms of an if...else... (only one of which will execute)? - or can there be arbitrary number of runScript calls within a given event block (each given its own script-thread)? As for use cases for *extensions* of runScript, what immediately comes to mind is to allow it to be in onTime and indeed every "on..." handler, so it can be used for debugging, by calling functions that in turn print to console. |
|
There can be any number of runScript, in if-s or not, last or not. It is executed like any other command. However, the command does not immediately call the script when executed. It only puts into into a buffer. When GUI script is over, all the script threads are created in "delayed" fashion (i.e. it will start at this or next frame --- not sure about details). This is of course true as long as someone pulls the information from the buffer... |
|
FYI, HMart in the past provided some code to extend namedEvents: https://forums.thedarkmod.com/index.php?/topic/20100-idtech-4-gui-scripting/#comment-439778 |
|
Wiki page "GUI Scripting: Commands" discussion of runScript is now updated to reflect info here. Check it out. | |
Yes, he provided a particular implementation: global event and immediate&nested execution. But he never questioned whether this is compatible with e.g. Quake 4 or not. |
|
I'm quite interested in getting the runScript functionality to work (better). First off, someone asked for possible use cases. I can give several. 1) In the recent thread https://forums.thedarkmod.com/index.php?/topic/22217-gui-displaying-different-sections-of-xdata-file/ , datiswous asked if it was possible to develop a template for an enhanced type of briefing where people could specify a different background for each page of text (possibly by having different xdata items for each page) 2) It would also make it easier to develop a in-game journal type of readable which is added to when the player does certain actions. A current example of this is done in the first mission (Monastery) of a House of Locked Secrets but the implementation is quite cumbersome because a) Each xdata item contains the whole contents of the 'previous' xdata item plus the added text. b) The in-game actions have to be performed in a pre-determined order. 3) Readables could be made more sophisticated e.g. having tabbed pages (e.g. in a paper address book). 4) You could have dynamic entity guis (e.g. destination displays at railway stations which change when the train has left). However for any of these to work properly, the scripting language will need to have access to the gui based variables ("text" etc). Scripts *can* access these but only if the qui has been created as an overlay. There are a number of script functions that manipulate gui variables but they all take an overlay handle as a parameter. This can be passed in by existing readable scripts because it has created the overlay in the first place - a script function called from a gui script won't have that value and that's assuming the overlay exists in the first place which won't be the case for briefings or entity guis. |
|
"But he never questioned whether this is compatible with e.g. Quake 4 or not." Fair enough. You asked some additional questions - as "(1)" above - that I can't really answer. I guess I thinking of this as analogous to a LMB press, that tries to find an onAttack handler in a stack of gui's. However, the fact of the match-by-name makes this more precise and also could (conceivably) be raise-one-event to many-event-handler-instances. I think I was just channeling HMart's namedEvent enthusiasm when I suggested this as a feature. Maybe this needs to be dropped or kicked down the road, pending a compelling use case. |
|
"However for any of these to work properly, the scripting language will need to have access to the gui based variables ("text" etc). Scripts *can* access these but only if the qui has been created as an overlay. There are a number of script functions that manipulate gui variables but they all take an overlay handle as a parameter. This can be passed in by existing readable scripts because it has created the overlay in the first place - a script function called from a gui script won't have that value and that's assuming the overlay exists in the first place which won't be the case for briefings or entity guis." There are other C++ internal pointers, such as "idUserInterface *gui", and maybe, with work, a pointer like that could be exposed and made viable for use when an overlay handle is not available? |
|
More elegant: if you have a custom non-overlay GUI, give it's (top-level only?) windowDef an FM-unique name, e.g., not "Desktop". Then there would be new script functions that take that name instead of an overlay handle. | |
Reading what boissiere wrote, I think none of the issues are solved simply by the "runScript" feature. In fact, similar cases inside core TDM are solved by having a persistent game thread which polls some GUI variables and modifies other GUI variables if necessary. That's how readables are implemented at least. Having GUI code run game scripts in this case is bad idea, because: 1) Having both GUI and script control some common state will cause terrible logical issues and race conditions. 2) GUI scripting are very bad in terms of features, and totally broken in terms of order of evaluation. ---------------- As for accessing entity GUI (i.e. the GUI which is attached to an entity via spawnarg in .map file), it is indeed possible to expose these GUIs (and their variables) to game scripts just like overlays. But this will work only for fully mission-defined GUIs, which are probably quit rare, no? I mean: TDM is not Sci-Fi with screens and computers... |
|
I have created forum thread: https://forums.thedarkmod.com/index.php?/topic/22239-gui-features-runscript-and-namedevent/ Perhaps migrate to there, since I guess these discussion can become quite lengthy =) |
|
I see your point about the very bad features and potential for logical/race issues. "As for accessing entity GUI (i.e. the GUI which is attached to an entity via spawnarg in .map file), it is indeed possible to expose these GUIs (and their variables) to game scripts just like overlays. But this will work only for fully mission-defined GUIs, which are probably quit rare, no? I mean: TDM is not Sci-Fi with screens and computers... " Perhaps this is chicken-and-egg... fully mission-defined GUIs may be rare to date because of lacking functionality. boisserie gave the train-station-schedule example. I think "magic mirror" effects, puzzles, and dynamic location maps could benefit. |
|
re "TDM is not Sci-Fi with screens and computers." Did TDM lose the computer screen ability that Doom 3 has? I can see mission authors wanting to mix in sci-fi elements. In fact, I have a mission in mind that I'd like to create that would use sci-fi computer screens. I recommend that we keep or restore in-game GUI screens. |
|
[quote]Did TDM lose the computer screen ability that Doom 3 has?[/quote] See: https://forums.thedarkmod.com/index.php?/topic/12987-interactive-gui-surface-question/ |
|
It is weird to call this issue "fixed", because: trivial p.3 was done it was learned that p.1 works as intended p.2 is not done I'm pretty sure the namedEvent command (p.2) should still remain in the bugtracker. |
|
Moving to 2.13 since there are open sub-tasks | |
I read this is moved to 2.13 . I thought I just mention this before 2.13 moves into beta. Although maybe you already do a search for this prior to beta (?) I personally don't understand namedevent, so cannot comment on it's functionality. |
|
The now-quiet forum discussion indicated some interest in namedEvent, but worries about implementation and use difficulties. Perhaps the pain-to-gain ratio is not promising at this time, and the idea should be moth-balled. I'm OK with that. | |
Date Modified | Username | Field | Change |
---|---|---|---|
14.11.2022 21:07 | stgatilov | New Issue | |
14.11.2022 21:07 | stgatilov | Status | new => assigned |
14.11.2022 21:07 | stgatilov | Assigned To | => stgatilov |
14.11.2022 21:16 | stgatilov | Product Version | => TDM 2.11 |
14.11.2022 21:16 | stgatilov | Target Version | => TDM 2.12 |
15.11.2022 20:10 | Geep | Note Added: 0015433 | |
04.10.2023 19:49 | stgatilov | Note Added: 0016099 | |
04.10.2023 21:11 | stgatilov | Note Added: 0016100 | |
05.10.2023 19:46 | stgatilov | Note Added: 0016105 | |
05.10.2023 19:46 | stgatilov | File Added: vec4_in_gui_hacky_background | |
05.10.2023 19:52 | stgatilov | Note Added: 0016106 | |
07.10.2023 16:35 | Geep | Note Added: 0016108 | |
07.10.2023 16:38 | Geep | Note Added: 0016109 | |
08.10.2023 07:35 | stgatilov | Note Added: 0016110 | |
08.10.2023 19:26 | Geep | Note Added: 0016111 | |
08.10.2023 19:49 | stgatilov | Note Added: 0016112 | |
09.10.2023 22:25 | Geep | Note Added: 0016113 | |
10.10.2023 02:20 | Geep | Note Added: 0016114 | |
10.10.2023 06:31 | stgatilov | Note Added: 0016115 | |
10.10.2023 18:47 | boissiere | Note Added: 0016116 | |
10.10.2023 18:53 | Geep | Note Added: 0016117 | |
11.10.2023 15:01 | Geep | Note Added: 0016118 | |
11.10.2023 15:52 | Geep | Note Added: 0016119 | |
11.10.2023 16:19 | stgatilov | Note Added: 0016120 | |
11.10.2023 16:39 | stgatilov | Note Added: 0016121 | |
11.10.2023 16:39 | stgatilov | Additional Information Updated | |
11.10.2023 17:21 | Geep | Note Added: 0016122 | |
11.10.2023 18:34 | Daft Mugi | Note Added: 0016123 | |
05.12.2023 01:48 | nbohr1more | Status | assigned => feedback |
19.12.2023 12:02 | datiswous | Note Added: 0016249 | |
04.02.2024 05:33 | nbohr1more | Status | feedback => resolved |
04.02.2024 05:33 | nbohr1more | Resolution | open => fixed |
04.02.2024 05:33 | nbohr1more | Fixed in Version | => TDM 2.12 |
04.02.2024 09:25 | stgatilov | Note Added: 0016478 | |
04.02.2024 13:30 | nbohr1more | Status | resolved => feedback |
04.02.2024 13:30 | nbohr1more | Resolution | fixed => reopened |
20.02.2024 18:16 | nbohr1more | Resolution | reopened => open |
20.02.2024 18:16 | nbohr1more | Fixed in Version | TDM 2.12 => |
20.02.2024 18:16 | nbohr1more | Target Version | TDM 2.12 => TDM 2.13 |
20.02.2024 18:17 | nbohr1more | Note Added: 0016539 | |
06.11.2024 11:23 | datiswous | Note Added: 0016900 | |
14.11.2024 22:30 | Geep | Note Added: 0016916 |