Global Variables

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
Pixel Eater
 
 
Posts: 667
Joined: Wed Aug 02, 2017 12:31 am
Location: In between the Moon and you, between the buried and me.

Global Variables

Post by Pixel Eater »

I'm trying to have a shader "fire-off" once each time I change a CVar and need some variables to persist outside of the main event handler. I've tried numerous ways of doing this and don't want to resort to storing them as extra CVars. I finally found this example (also here) of storing global variables but for some reason it's not behaving globally?

Code: Select all

version "2.5"
#include "ZScript/ThermalImp.zc"

class MyGlobalVariables : Thinker
{
	int prevstate;
	double start_time ;

	MyGlobalVariables Init()
	{
		PlayerInfo p = players[ consoleplayer ];
		prevstate = Cvar.GetCVar( "gl_thermalcam", p ).GetInt();
		start_time = 0 ;
		ChangeStatNum(STAT_STATIC);
		return self;
	}

	static MyGlobalVariables Get()
	{
		ThinkerIterator it = ThinkerIterator.Create("MyGlobalVariables", STAT_STATIC);
		let q = MyGlobalVariables(it.Next());
		if (q == null)
		{
			q = new("MyGlobalVariables").Init();
		}
		return q;
	}
}

class ThermalCamHandler : EventHandler
{
	override void RenderOverlay( RenderEvent e )
	{
		PlayerInfo p = players[ consoleplayer ];
		let g = MyGlobalVariables.Get();              //Causes the error: "Can't call play function get from ui context"
		double timer = gametic + e.fracTic ;
		
		if( Cvar.GetCVar( "gl_thermalcam", p ).GetInt() == 1 )
		{
			if( g.prevstate == 0 )
			{
				g.start_time = timer ;
				g.prevstate = 1 ;
			}
			Shader.SetEnabled( p, "ThermalCam", true );
		}
		else
		{
			if( g.prevstate == 1 )
			{
				g.start_time = timer ;
				g.prevstate = 0 ;
			}
			Shader.SetEnabled( p, "ThermalCam", false );
		}
		
		double timeleft = 1.0 - ( timer - g.start_time );
		if( timeleft > 0 )
		{
			Shader.SetUniform1f( p, "Shutter", "countdown", timeleft * 39 + 1 );
			Shader.SetEnabled( p, "Shutter", true );
		}
		else Shader.SetEnabled( p, "Shutter", false );
	}
}
So everytime it checks the 'gl_thermalcam' CVar, it looks to see what the previous value (g.prevstate) was to determine if it has changed and if so, updates 'g.start_time' with the current timer value. From this it can be determined how much time has passed since 'ThermalCam' was toggled and when ZScript should disable the 'Shutter' shader.

That's the theory except that the line 'let g = MyGlobalVariables.Get();' causes an error: "Can't call play function get from ui context". Which if it is in fact global, means I'm doing something wrong. Or should I just stick to using CVars as I've done before?
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Global Variables

Post by gwHero »

The construction of your global object seems ok, but there is one place where you cannot use them, and that is from UI scope. So you cannot do this from RenderOverlay. But there are more restrictions to UI scope: you also cannot change data there, so even if you would move it to local variables of the ThermalCamHandler class, you could still not change it's variables in RenderOverlay (in RenderOverlay you can only change variables that are declared in RenderOverlay itself).

One thing you could do is replacing the RenderOverlay by the WorldTick event, and move all code in RenderOverlay to WorldTick.
However, since you do not have the e.fractic variable there, you would have to do the counting down with an extra variable in the ThermalCamHandler class.

Something like this I think might work:

Code: Select all

class ThermalCamHandler : EventHandler
{
   int mytic;
   override void WorldTick()
   {
       if (!mytic) mytic = 0; // initialize 
       mytic++;

// put here rest of the code you now have in renderoverlay ; replace e.fractic by mytic
   }
}
Now this is an example that doesn't change much to your code; I think it could be done a bit more straightforward without the use of a thinker and a eventhandler class, and just with one thinker, but that's a bit irrelevant for the problem here.

EDIT: I don't know much about Shaders; I'm not sure if they are restricted to UI scope; if that's the case you would have to split it, and keep only the shader part in RenderOverlay.
User avatar
Pixel Eater
 
 
Posts: 667
Joined: Wed Aug 02, 2017 12:31 am
Location: In between the Moon and you, between the buried and me.

Re: Global Variables

Post by Pixel Eater »

Thanks gwHero, that did the trick :D

Code: Select all

version "2.5"
#include "ZScript/ThermalImp.zc"

class ThermalCamHandler : EventHandler //Thanks to gwHero for being a hero! :D
{
	int prevstate ;
	int mytic ;
	override void WorldTick()
	{
		PlayerInfo p = players[ consoleplayer ];
		if( !prevstate ) prevstate = Cvar.GetCVar( "gl_thermalcam", p ).GetInt() ;
		if( !mytic ) mytic = 0 ;		
		
		if( Cvar.GetCVar( "gl_thermalcam", p ).GetInt() == 1 )
		{
			if( prevstate < 2 )
			{
				mytic = 5 ;
				prevstate = 2 ;
			}
			Shader.SetEnabled( p, "ThermalCam", true );
		}
		else
		{
			if( prevstate == 2 )
			{
				mytic = 5 ;
				prevstate = 1 ;
			}
			Shader.SetEnabled( p, "ThermalCam", false );
		}
		
		if( mytic > 0 )
		{
			Shader.SetUniform1f( p, "Shutter", "countdown", mytic << 3 );
			Shader.SetEnabled( p, "Shutter", true );
			mytic-- ;
		}
		else Shader.SetEnabled( p, "Shutter", false );
	}
}
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Global Variables

Post by gwHero »

Very nice :)
User avatar
Pixel Eater
 
 
Posts: 667
Joined: Wed Aug 02, 2017 12:31 am
Location: In between the Moon and you, between the buried and me.

Re: Global Variables

Post by Pixel Eater »

I just posted this .gif of the shutter effect working on the WIP thread: Spectral Ninjas :D
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: Global Variables

Post by gwHero »

Pixel Eater wrote:I just posted this .gif of the shutter effect working on the WIP thread: Spectral Ninjas :D
That's really cool ! :)

Return to “Scripting”