Game Development Community

need a function to check if playback has been stopped and then popDialog.

by Ahsan Muzaheed · in Torque 3D Beginner · 08/27/2011 (5:27 am) · 12 replies

i was trying to make a function to play video in different places.
so i have made a GuiTheoraCtrl and related functions.it works and plays well.
but after finishing the play, the GuiTheoraCtrl still remains over playGui.
so have to paste Canvas.popDialog(videoLayer); in console.

so to do it in script, i have made a function to check if the video playing has finished or not
(isPlaybackDone()).well,it works only for 2/3 seconds.then stopped.
it seems all the problem is in function check().

*1st make a file named videoLayer.cs in game folder.

*paste this code in that file:
//--- OBJECT WRITE BEGIN ---
 %guiContent = new GuiTheoraCtrl(videoLayer) {
   backgroundColor = "0 0 0 255";
   playOnWake = "1";
   stopOnSleep = "1";
   matchVideoSize = "0";
   renderDebugInfo = "0";
   transcoder = "Auto";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 2";
   horizSizing = "windowRelative";
   vertSizing = "windowRelative";
   profile = "GuiDefaultProfile";
   visible = "1";
   active = "1";
   tooltipProfile = "GuiToolTipProfile";
   hovertime = "1000";
   isContainer = "1";
   canSave = "1";
   canSaveDynamicFields = "1";
}; 
//--- OBJECT WRITE END ---

function playVideo(%file)
{
	videoLayer.theoraFile=%file;
	Canvas.pushDialog(videoLayer);
}


function check()
{
if(!videoLayer.isPlaybackDone())
{
echo("playing");
$d=schedule(2000,0,check);
}
else  if(videoLayer.isPlaybackDone())
{
//cancel($d);
echo("stopped");
Canvas.popLayer();
//Canvas.popLayer(1);
//Canvas.popLayer(0);
//videoLayer.delete();
//videoLayer.deleteAllObjects();
//Canvas.popDialog(videoLayer);
//Canvas.pushDialog(PlayGui);
}

}

function videoLayer::onWake(%this)
{
       
	echo("going to play"@videoLayer.theoraFile);
	//check();//comment it,all will work well,but videoLayer will remain in screen
}

 function videoLayer::onSleep(%this)  
{  
	videoLayer.theoraFile = "";
	echo("going to sleep with"@videoLayer.theoraFile);    
}  



 function videoLayer::onStop(%this)  
{  
	echo("why i never called!!!!!!!!??????????");    
}

*now exec it at the end of the main.cs file of game folder.

*if u do not have any *.ogv file.then make one by pasting it in console:
recordMovie("myMovie",25)

after a few second paste this:
stopMovie()
now u will have a myMovie.ogv in game folder.

*start your XXX.exe
now in console paste this:
playVideo("myMovie.ogv").

video will play.after that there will be the GuiTheoraCtrl in screen(a black screen).
now type check().it will be checked and pop it up.so here check() it works fine.no problem.

*now uncomment the check() call in onWake().and do the same thing.u will see sometimes it work,sometimes not.all goes crazy.most of the time it will play for 2/3 second.then stopped.and that is the problem.it need to call in onWake().but in onWake() it is not working.


i have searched the forum.found two same problem on what to do after finishing play.but they r still unsolved.
here is one:
www.garagegames.com/community/forums/viewthread/61231
(forgot anothe one,will post when will find again)

also have found a solution.but not for me:
www.garagegames.com/community/blogs/view/16617

where is the fault,in check()?
an alternative will be good.but i need to know why check() is not doing it well.

About the author

Torque 3D enthusiastic since 2010.Have been working in several T3D projects besides of Unreal Engine 4 and Unity 3D. NEED a hand with your project? SHoot me a mail. http://www.garagegames.com/community/forums /viewthread/138437/


#1
08/27/2011 (6:45 am)
instead of check() i entered a while () at the end of onWake() function:
here is the modified onWake function

function videoLayer::onWake(%this)
{
  echo("going to play"@videoLayer.theoraFile);
	//check();
	
while(!videoLayer.isPlaybackDone())
{
echo("playing");
}
echo("stopped");
Canvas.popDialog(videoLayer);
	
}

but using while makes the whole game hangs.
why this always happend for "while"?
#2
08/27/2011 (2:42 pm)
Hi muzaheed,

The game hangs because the onWake function is being called from the main Thread, then gets stuck in the eternal while(!videoLayer.isPlaybackDone()) loop.

to add a onDone call back...
in guiTheoraCtrl.cpp find in GuiTheoraCtrl::onRender method

else
mDone = true;

change to..

else
{
mDone = true;
Con::executef( this, "onDone" );
}

and add to the end of GuiTheoraCtrl::stop() method..

Con::executef( this, "onDone" );

you 'should' hopefully have a callback to script...
videoLayer::onDone()

I havn't tested this, but I think that should work.

John
#3
08/27/2011 (2:56 pm)
Thanks.i will try that.onDone seems like onStop.
#4
08/27/2011 (4:21 pm)
Jonajoint,i have tried but nothing happened.here is the modified code :
GuiTheoraCtrl::onRender method:

if( mTheoraTexture.isReady() )
	{
      mTheoraTexture.refresh();
      if( mTheoraTexture.isPlaying()
          || mTheoraTexture.isPaused() )
      {
         // Draw the frame.
         
         GFXDrawUtil* drawUtil = GFX->getDrawUtil();
         drawUtil->clearBitmapModulation();
         drawUtil->drawBitmapStretch( mTheoraTexture.getTexture(), rect );
         
         // Draw frame info, if requested.
         
         if( mRenderDebugInfo )
         {
            String info = String::ToString( "Frame Number: %i | Frame Time: %.2fs | Playback Time: %.2fs | Dropped: %i",
               mTheoraTexture.getFrameNumber(),
               mTheoraTexture.getFrameTime(),
               F32( mTheoraTexture.getPosition() ) / 1000.f,
               mTheoraTexture.getNumDroppedFrames() );
            
            drawUtil->setBitmapModulation( mProfile->mFontColors[ 0 ] );
            drawUtil->drawText( mProfile->mFont, localToGlobalCoord( Point2I( 0, 0 ) ), info, mProfile->mFontColors );
         }
      }
      else
			{//add
			mDone = true;
			Con::executef( this, "onDone" );
			}//add


and modified GuiTheoraCtrl::stop() method:

void GuiTheoraCtrl::stop()
{
	mTheoraTexture.stop();
	mDone = true;
	Con::executef( this, "onDone" );
}

then in script(videoLayer.cs) added:

function videoLayer::onDone(%this)  
{  
  echo("hi i am from onDone()");   
  Canvas.popDialog(videoLayer); 
}

but nothing in console from videoLayer::onDone()???????????????
#5
08/27/2011 (4:40 pm)
ok i'll have a better look..
#6
08/27/2011 (5:16 pm)
ok sorry muzzaheed my bad advice :p

in guiTheoraControl.h

under
protected:

add

DECLARE_CALLBACK( void, onDone, () );
bool hasThrownOnDone;
void throwOnDone();

in guiTheoraControl.cpp
at top under IMPLEMENT_CONOBJECT( GuiTheoraCtrl );
add
IMPLEMENT_CALLBACK( GuiTheoraCtrl, onDone, void, (), (),
"Called when the Video has stopped playing." );

in constructor (GuiTheoraCtrl::GuiTheoraCtrl)
add
hasThrownOnDone=true;

in the GuiTheoraCtrl::play()
add
hasThrownOnDone=false;

at end of file add

void GuiTheoraCtrl::throwOnDone()
{
hasThrownOnDone=true;
onDone_callback();
}

and replace the other Con::executef( this, "onDone" );
with
throwOnDone();


this will still throw the callback twice on level start though, but will get you going..
i'm currently on irc if it would be easier
#7
08/27/2011 (5:23 pm)
ok forgot something change the throwOnDone() method to...

void GuiTheoraCtrl::throwOnDone()
{
if(!hasThrownOnDone){
hasThrownOnDone=true;
onDone_callback();
}
}
#8
08/28/2011 (9:48 am)
Ok fixed the crashing issue..

function videoLayer::onDone(%this)
{
echo("Theora Video Done!");
%this.schedule(1000,popDialog);
}
function videoLayer::popDialog(%this)
{
Canvas.popDialog(videoLayer);
}

It was crashing because the theora control wasnt geting chance to do its stuff before we popped the dialog..
this now works and has been tested countless times with different settings..
It could do with being done a better way, but this should get you by untill you either beg/pay someone to do it :p
or GG implements the functionality.
#10
08/29/2011 (1:09 am)
jonajoint,plz test this code in u r project.if this works well for u then i have to say problem is somewhere in my scripts.then i will try to find that.

file name: videoLayer.cs
//--- OBJECT WRITE BEGIN ---
 %guiContent = new GuiTheoraCtrl(videoLayer) {
   backgroundColor = "0 0 0 255";
   playOnWake = "1";
   stopOnSleep = "1";
   matchVideoSize = "0";
   renderDebugInfo = "0";
   transcoder = "Auto";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 2";
   horizSizing = "windowRelative";
   vertSizing = "windowRelative";
   profile = "GuiDefaultProfile";
   visible = "1";
   active = "1";
   tooltipProfile = "GuiToolTipProfile";
   hovertime = "1000";
   isContainer = "1";
   canSave = "1";
   canSaveDynamicFields = "1";
}; 
//--- OBJECT WRITE END ---

function playVideo(%file)
{
	videoLayer.theoraFile=%file;
	Canvas.pushDialog(videoLayer);
}

function videoLayer::onWake(%this)
{
	echo("going to play"@videoLayer.theoraFile);
	//check();//comment it,all will work well,but videoLayer will remain in screen
}

 function videoLayer::onSleep(%this)  
{  
	videoLayer.theoraFile = "";
	echo("going to sleep with"@videoLayer.theoraFile);    
}  

function videoLayer::onDone(%this)
{
echo("Theora Video Done!");
%this.schedule(10000,popDialog);
}


function videoLayer::popDialog(%this)
{
Canvas.popDialog(videoLayer);
}

* at the end of game/main.cs add:
exec("videoLayer.cs");
*in main menu paste this in console
playVideo("myMovie.ogv");

waiting for u r result.
#11
08/29/2011 (1:10 pm)
yeh that works everytime for me..

the only difference is i'm execing the gui in scripts/client/init.cs

in the block
// Load up the Game GUIs

#12
08/29/2011 (1:11 pm)
oh and do you really want the schedule set to 10 seconds?
I thought it had hung at first :p