alreadyInTransition issue with FSM

Howdy everyone,

I’ve recently started working on a project in panda3d. Currently what i’m doing is loading up an intro video and then whenever the user presses escape transitioning from the intro state with the FSM to the main state which is where I build my mainmenu. However, i’ve poured over sample code and other forum posts and can’t see what im doing wrong. I have the handler accept the esc key which then runs a function that transitions to another state but the program crashes saying already in transition from off to intro. I put a check in to confirm that the state is in intro before requesting a transition and now it runs but it wont accept the esc key no matter how many times/when i press it. it just keeps playing my video till the end. Please see attached code below. Im quite confused why this is occuring.

class introMovie(DirectObject):
  def __init__(self):
      # create Intro crap
      self.introVideo="intro.mp4"
      # Load the texture. We could use loader.loadTexture for this,
      # but we want to make sure we get a MovieTexture, since it
      # implements synchronizeTo.
      self.introTex = MovieTexture("name")
      assert self.introTex.read(self.introVideo), "Failed to load video!"

      # Set up a fullscreen card to set the video texture on.
      cm = CardMaker("My Fullscreen Card");
      cm.setFrameFullscreenQuad()
      self.introCard = NodePath(cm.generate())
      self.introCard.reparentTo(render2d)
      self.introCard.setTexture(self.introTex)
      self.introCard.setTexScale(TextureStage.getDefault(), self.introTex.getTexScale())
      self.introSound=loader.loadSfx(self.introVideo)
      # Synchronize the video to the sound.
      self.introTex.synchronizeTo(self.introSound)
      self.accept( 'escape', self.checkQuit)

  def introPlay(self):
      self.introSound.play()

  def checkQuit(self):
	    if (str(applicationFSM.state) == "intro"):
	        self.interruptIntro()
	
  def interruptIntro(self):
      applicationFSM.request( 'Main' )

  def cleanup(self):
      self.introSound.stop()
      self.introCard.removenode()
    

I tried checking the state without turning it into a str first as well.

If I didn’t use the check I tried one of too ways. just assign the accept to use interruptIntro rather than checkQuit or assign the FSM request directly to the accept for the escape key. Help would be greatly appreciated! Thanks in advance :slight_smile:
[/code]

Is your intro state ‘Intro’ with a capital ‘I’? If not, change it so that it is. It says capitalized is “by convention” but looking at the source I see several checks for it so it may actually be a requirement.

If you still can’t solve it you should post the code for that applicationFSM because that’s likely where the problem is. If it is too big at least post the relevant parts like enterIntro, defaultTransitions/defaultFilter (if present), etc.

Yes it’s capitalized and transitions to intro just fine. Code for the FSM as is is below

class applicationFSM(FSM.FSM):
 
    def __init__(self):
        # must be called
        FSM.FSM.__init__(self, 'applicationFSM')
        self.defaultTransitions = {
            'Intro' : [ 'Main' ],
            'Main' : [ 'Newgame', 'Game', 'Quit' ],
            'Newgame' : [ 'Game' ],
            'Quit' : [ ],
            'Game' : [ 'Game2Main' ],
            'Game2Main' : [ 'Main' ],
            } 

    def enterIntro(self):
        self.introMovie=introMovie()
        self.introMovie.introPlay()

    def exitIntro(self):
        # exit Intro crap(stopping playback and removing the introduction video and its card from memory)
        self.introMovie.cleanup()

    def enterMain(self):
        self.mainMenu=mainMenu()

    def exitMain(self):
        # exit Main menu, simply hides since we will use it whenever player presses esc
        self.mainMenu.hideMainMenu()

Ok I solved the problem thanks to Hollower’s nub reminder lol I had the fsm.state function testing for lowercase intro not uppercase sigh I thought I did everything right too. Anywho it now works, I also should mention I didnt capitalize removeNode() in my cleanup code either so the change I needed to make in checkQuit was

  def checkQuit(self):
      if (applicationFSM.state == "Intro"):
	        self.interruptIntro()

and in cleanup

  def cleanup(self):
      self.introSound.stop()
      self.introCard.removeNode()

Thanks for your help Hollower :slight_smile:

The reason I asked is because you wrote

if (str(applicationFSM.state) == "intro"):

with a lowercase ‘i’ and string comparisons are case sensitive.

class applicationFSM(FSM.FSM):

Hmmm, that can’t be right. Here it looks like your class name is applicationFSM, and in introMovie you call applicationFSM.request( ‘Main’ ). That should fail because applicationFSM is not an instance, so you’d be attempting to call an unbound method. Do you instantiate this class anywhere? Do you know what I’m talking about?

Oh looks like you posted while I was writing. I’m glad you got it working. I also notice enterMain creates a new menu every time, but exitMain only “hides” it. Remember it will call enterMain whenever it transitions back to that state, overwriting that self.mainMenu variable.

Sure do, my state manager is how I managed the entire program. So the Intro class and other subsequent classes are all children of applicationFSM object and have access to the parent. I took this concept from a spaceship sample I saw on the forums(you can tell alot of the beginning code is from samples) I’ve never worked in python before. I’ve mainly written in c and c++ for the past 14 years in a unix environment with an occasional sample of things like lua, perl, or java to name a few whenever I got the madscientist bug and decided I needed to write something in them. so i’m working from example for the majority and it’s my first solid attempt at working with anything 3d.

# create application instance
applicationFSM = applicationFSM( )
applicationFSM.request( 'Intro' ) # go into menu state
# change window properties
winProps = WindowProperties()
winProps.clear( )
winProps.setTitle( 'Test Project' )
# request changes
base.win.requestProperties( winProps )
# run
if __name__ == '__main__': 
    run( ) # if this module is not being imported run the game

You can see I create the intromovie object in the enterIntro state of the fsm below

    def enterIntro(self):
        self.introMovie=introMovie()
        self.introMovie.introPlay()

    def exitIntro(self):
        # exit Intro crap(stopping playback and removing the introduction video and its card from memory)
        self.introMovie.cleanup()

Oh crap your right I was thinking I only needed to deal with testing to see if mainMenu existem in my game2main transition. I’ll add the check now thx :slight_smile: