UE2 - UT2kX Problem with Canvas's DrawPortal function

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

EvilT-ModZ

Un-Gravitify
Aug 3, 2011
42
0
6
30
Russia
www.set-games.ru
Hello,

I wrote simple code with drawportal function, original idea by Luke Wenke.

Code:
class RevelationGameHUD extends MpHUD;

var Actor PortalActor;

simulated function PostRender(Canvas Canvas)
{
	DrawPortals(Canvas);
	Super.PostRender(Canvas);
}

simulated function DrawPortals(Canvas Canvas)
{
	local Actor TestPortalActor;

	if( PortalActor == None )
	{
		foreach AllActors(class'Actor', TestPortalActor)
		{
			if( TestPortalActor != None && TestPortalActor.IsA('Projectile') )
			{
				PortalActor = TestPortalActor;
				break;
			}
		}
	}

	Canvas.Reset();
	Canvas.Font = Canvas.MedFont;
	Canvas.DrawColor.r = 255;
	Canvas.DrawColor.g = 255;
	Canvas.DrawColor.b = 255;

	if( PortalActor != None )
	{
		Canvas.DrawBox(Canvas,Canvas.SizeX*0.3,Canvas.SizeY*0.3);
		Canvas.DrawPortal(0,0,Canvas.SizeX*0.3,Canvas.SizeY*0.3,self,PortalActor.Location -40 * vector(PortalActor.Rotation),PortalActor.Rotation,90);

		Canvas.SetPos(Canvas.SizeX*0.02, Canvas.SizeY*0.05);
		Canvas.DrawText("Projectile portal cam");

		Canvas.SetPos(Canvas.SizeX*0.02, Canvas.SizeY*0.25);
		Canvas.DrawText("Proj_name: "$PortalActor.Name);
	}
}

But, the game is crashing when code calls DrawPortal.

Code:
Assertion failed: SavedStateIndex+1 < MAX_STATESTACKDEPTH [File:C:\Projects\Postal2\prog\Warfare\D3DDrv\Src\D3DRenderInterface.cpp] [Line: 159]

History: F3DRenderInterface::PushState <- FBspDrawList::Render <- 
RenderLevel <- FLevelSceneNode::Render <- FCameraSceneNode::Render <-
 UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1, Function 
Postal2Game.P2HUD.PostRender) <- FCameraSceneNode::Render <- 
UCanvas::execDrawPortal <- (RevelationGameHUD mpRevelation-
ExperimentalTest.RevelationGameHUD1 @ Function 
P2RevelationGame.RevelationGameHUD.DrawPortals : 017E) <- 
UObject::ProcessEvent <- (RevelationGame

Game is Postal 2
This code is working in UT2k3 and UT2k4
 

Wormbo

Administrator
Staff member
Jun 4, 2001
5,913
36
48
Germany
www.koehler-homepage.de
Careful with DrawPortal. It not only draws the world view from the specified location, but also calls the specified actor's PostRender, potentially causing another HUD being drawn inside the portal view. That seems to be what happened in your case, as DrawPortal recursively called itself.

Make absolutely sure the portal is drawn with a camera actor that does not cause the HUD to be drawn through its PostRender.
 

EvilT-ModZ

Un-Gravitify
Aug 3, 2011
42
0
6
30
Russia
www.set-games.ru
Thank you Wormbo for reply,

I've tried to make an interaction, so, I think it's other PostRender

Code:
class PortalInteraction extends Interaction;

var PlayerController PlayerOwner;

function PostRender(Canvas C)
{
	local Actor PortalActor;

	if( PlayerOwner == None )
		PlayerOwner = ViewportOwner.Actor;

	PortalActor = FindAnyPortalActor(PlayerOwner);

	if( PortalActor != None && PlayerOwner != None )
		C.DrawPortal(0, 0, C.SizeX*0.3, C.SizeY*0.3, PlayerOwner,PortalActor.Location,PortalActor.Rotation);
}

function Actor FindAnyPortalActor(Actor ObjectOwner)
{
	local Projectile ProjActor;
	foreach ObjectOwner.AllActors(class'Projectile',ProjActor)
	if( ProjActor != None )
		return ProjActor;
	return None;
}

defaultproperties
{
	 bVisible=True
}

But, it causes same crit =/

Code:
Assertion failed: SavedStateIndex+1 < MAX_STATESTACKDEPTH 
[File:C:\Projects\Postal2\prog\Warfare\D3DDrv\Src\D3DRenderInterface.cpp]
 [Line: 159]

History: F3DRenderInterface::PushState <- FBspDrawList::Render <- 
RenderLevel <- FLevelSceneNode::Render <- FCameraSceneNode::Render <-
 UCanvas::execDrawPortal <- (PortalInteraction 
Transient.InteractionMaster0.PortalInteraction0 @ Function 
PortalTests.PortalInteraction.PostRender : 00A9) <- UObject::ProcessEvent
 <- (InteractionMaster Transient.InteractionMaster0, Function 
Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <- (InteractionMaster Transient.InteractionMaster0, 
Function Engine.InteractionMaster.Process_PostRender) <- 
UInteractionMaster::MasterProcessPostRender <- 
FCameraSceneNode::Render <- UCanvas::execDrawPortal <- 
(PortalInteraction Transient.InteractionMaster0.PortalInteraction0 @ 
Function PortalTests.PortalInteraction.PostRender : 00A9) <- 
UObject::ProcessEvent <-

I have no ideas, probably this function is wrecked in this build?
 

Wormbo

Administrator
Staff member
Jun 4, 2001
5,913
36
48
Germany
www.koehler-homepage.de
Hmm, in that case DrawPortal probably is broken in your game. What if you add a "recursion blocker" into your code. The simplest version would be to simply declare your drawing function as "singular". A more elaborate approach would include a class-global bool variable that you test to ensure it's False and then set to True after the check and to False again upon leaving the function.
 
Last edited:

EvilT-ModZ

Un-Gravitify
Aug 3, 2011
42
0
6
30
Russia
www.set-games.ru
Hmm, in that case DrawPortal probably is broken in your game. What if you add a "recursion blocker" into your code. The simplest version would be to simply declare your drawing function as "singular". A more elaborate approach would include a class-global bool variable that you test to ensure it's False and then set to True after the check and to False again upon leaving the function.

Oh god, it works :)

Code:
function PostRender(Canvas C)
{
	DrawPortals(C);
	C.SetPos(C.SizeX*0.02, C.SizeY*0.25);
	C.DrawText("TestRecursion: "$bTestRecursion);
}

singular function DrawPortals(Canvas C)
{
	local Actor PortalActor;

	bTestRecursion = true;
	if( PlayerOwner == None )
		PlayerOwner = ViewportOwner.Actor;

	PortalActor = FindAnyPortalActor(PlayerOwner);

	if( PortalActor != None && PlayerOwner != None )
	{
		C.DrawBox(C,C.SizeX*0.32,C.SizeY*0.32);
		C.DrawPortal(0, 0, C.SizeX*0.3, C.SizeY*0.3, PortalActor,PortalActor.Location,PortalActor.Rotation);

		C.SetPos(C.SizeX*0.02, C.SizeY*0.02);
		C.DrawText("Projectile portal cam");
	}
	bTestRecursion = false;
}

Interesting fact about it's recursion anomaly, doubling player's hud and etc, but I belive it's fixable problem.

Thank you a lot Wormbo ! :)
 

Attachments

  • Shot00002.jpg
    Shot00002.jpg
    602.1 KB · Views: 26