Пример #1
0
    def makeState(self, parentState, animationFileName):
        topLevel = QState(parentState)

        animation = Animation()

        file = QFile(animationFileName)
        if file.open(QIODevice.ReadOnly):
            animation.load(file)

        frameCount = animation.totalFrames()
        previousState = None
        for i in range(frameCount):
            animation.setCurrentFrame(i)

            frameState = QState(topLevel)
            nodeCount = animation.nodeCount()
            for j in range(nodeCount):
                frameState.assignProperty(self.m_stickMan.node(j), 'pos',
                                          animation.nodePos(j))

            frameState.setObjectName('frame %d' % i)

            if previousState is None:
                topLevel.setInitialState(frameState)
            else:
                previousState.addTransition(previousState.propertiesAssigned,
                                            frameState)

            previousState = frameState

        previousState.addTransition(previousState.propertiesAssigned,
                                    topLevel.initialState())

        return topLevel
Пример #2
0
    def makeState(self, parentState, animationFileName):
        topLevel = QState(parentState)

        animation = Animation()

        file = QFile(animationFileName)
        if file.open(QIODevice.ReadOnly):
            animation.load(file)

        frameCount = animation.totalFrames()
        previousState = None
        for i in range(frameCount):
            animation.setCurrentFrame(i)

            frameState = QState(topLevel)
            nodeCount = animation.nodeCount()
            for j in range(nodeCount):
                frameState.assignProperty(self.m_stickMan.node(j), "pos", animation.nodePos(j))

            frameState.setObjectName("frame %d" % i)

            if previousState is None:
                topLevel.setInitialState(frameState)
            else:
                previousState.addTransition(previousState.propertiesAssigned, frameState)

            previousState = frameState

        previousState.addTransition(previousState.propertiesAssigned, topLevel.initialState())

        return topLevel
Пример #3
0
def twoStateButton(name,stateMachine,action,*states):
    st = QStateMachine()

    a1,a2 = states
    s1,s2 = QState(),QState()
    icon1 = QIcon(Icons + a1[1])
    icon2 = QIcon(Icons + a2[1])
    s1.setObjectName(a1[0])
    s2.setObjectName(a2[0])
    s1.assignProperty(action, "icon", icon1)
    s2.assignProperty(action, "icon", icon2)
    s1.assignProperty(action, "text", a1[0])
    s2.assignProperty(action, "text", a2[0])

    s1.addTransition(action.triggered, s2)
    s2.addTransition(action.triggered, s1)
    st.addState(s1)
    st.addState(s2)
    st.setInitialState(s1)

    stateMachine[name] = st
    st.start()
Пример #4
0
class LifeCycle(object):
    def __init__(self, stickMan, keyReceiver):
        self.m_stickMan = stickMan
        self.m_keyReceiver = keyReceiver

        # Create animation group to be used for all transitions.
        self.m_animationGroup = QParallelAnimationGroup()
        stickManNodeCount = self.m_stickMan.nodeCount()
        self._pas = []
        for i in range(stickManNodeCount):
            pa = QPropertyAnimation(self.m_stickMan.node(i), 'pos')
            self._pas.append(pa)
            self.m_animationGroup.addAnimation(pa)

        # Set up intial state graph.
        self.m_machine = QStateMachine()
        self.m_machine.addDefaultAnimation(self.m_animationGroup)

        self.m_alive = QState(self.m_machine)
        self.m_alive.setObjectName('alive')

        # Make it blink when lightning strikes before entering dead animation.
        lightningBlink = QState(self.m_machine)
        lightningBlink.assignProperty(self.m_stickMan.scene(),
                                      'backgroundBrush', Qt.white)
        lightningBlink.assignProperty(self.m_stickMan, 'penColor', Qt.black)
        lightningBlink.assignProperty(self.m_stickMan, 'fillColor', Qt.white)
        lightningBlink.assignProperty(self.m_stickMan, 'isDead', True)

        timer = QTimer(lightningBlink)
        timer.setSingleShot(True)
        timer.setInterval(100)
        lightningBlink.entered.connect(timer.start)
        lightningBlink.exited.connect(timer.stop)

        self.m_dead = QState(self.m_machine)
        self.m_dead.assignProperty(self.m_stickMan.scene(), 'backgroundBrush',
                                   Qt.black)
        self.m_dead.assignProperty(self.m_stickMan, 'penColor', Qt.white)
        self.m_dead.assignProperty(self.m_stickMan, 'fillColor', Qt.black)
        self.m_dead.setObjectName('dead')

        # Idle state (sets no properties).
        self.m_idle = QState(self.m_alive)
        self.m_idle.setObjectName('idle')

        self.m_alive.setInitialState(self.m_idle)

        # Lightning strikes at random.
        self.m_alive.addTransition(LightningStrikesTransition(lightningBlink))
        lightningBlink.addTransition(timer.timeout, self.m_dead)

        self.m_machine.setInitialState(self.m_alive)

    def setDeathAnimation(self, fileName):
        deathAnimation = self.makeState(self.m_dead, fileName)
        self.m_dead.setInitialState(deathAnimation)

    def start(self):
        self.m_machine.start()

    def addActivity(self, fileName, key):
        state = self.makeState(self.m_alive, fileName)
        self.m_alive.addTransition(
            KeyPressTransition(self.m_keyReceiver, key, state))

    def makeState(self, parentState, animationFileName):
        topLevel = QState(parentState)

        animation = Animation()

        file = QFile(animationFileName)
        if file.open(QIODevice.ReadOnly):
            animation.load(file)

        frameCount = animation.totalFrames()
        previousState = None
        for i in range(frameCount):
            animation.setCurrentFrame(i)

            frameState = QState(topLevel)
            nodeCount = animation.nodeCount()
            for j in range(nodeCount):
                frameState.assignProperty(self.m_stickMan.node(j), 'pos',
                                          animation.nodePos(j))

            frameState.setObjectName('frame %d' % i)

            if previousState is None:
                topLevel.setInitialState(frameState)
            else:
                previousState.addTransition(previousState.propertiesAssigned,
                                            frameState)

            previousState = frameState

        previousState.addTransition(previousState.propertiesAssigned,
                                    topLevel.initialState())

        return topLevel
Пример #5
0
class LifeCycle(object):
    def __init__(self, stickMan, keyReceiver):
        self.m_stickMan = stickMan
        self.m_keyReceiver = keyReceiver

        # Create animation group to be used for all transitions.
        self.m_animationGroup = QParallelAnimationGroup()
        stickManNodeCount = self.m_stickMan.nodeCount()
        self._pas = []
        for i in range(stickManNodeCount):
            pa = QPropertyAnimation(self.m_stickMan.node(i), b"pos")
            self._pas.append(pa)
            self.m_animationGroup.addAnimation(pa)

        # Set up intial state graph.
        self.m_machine = QStateMachine()
        self.m_machine.addDefaultAnimation(self.m_animationGroup)

        self.m_alive = QState(self.m_machine)
        self.m_alive.setObjectName("alive")

        # Make it blink when lightning strikes before entering dead animation.
        lightningBlink = QState(self.m_machine)
        lightningBlink.assignProperty(self.m_stickMan.scene(), "backgroundBrush", Qt.white)
        lightningBlink.assignProperty(self.m_stickMan, "penColor", Qt.black)
        lightningBlink.assignProperty(self.m_stickMan, "fillColor", Qt.white)
        lightningBlink.assignProperty(self.m_stickMan, "isDead", True)

        timer = QTimer(lightningBlink)
        timer.setSingleShot(True)
        timer.setInterval(100)
        lightningBlink.entered.connect(timer.start)
        lightningBlink.exited.connect(timer.stop)

        self.m_dead = QState(self.m_machine)
        self.m_dead.assignProperty(self.m_stickMan.scene(), "backgroundBrush", Qt.black)
        self.m_dead.assignProperty(self.m_stickMan, "penColor", Qt.white)
        self.m_dead.assignProperty(self.m_stickMan, "fillColor", Qt.black)
        self.m_dead.setObjectName("dead")

        # Idle state (sets no properties).
        self.m_idle = QState(self.m_alive)
        self.m_idle.setObjectName("idle")

        self.m_alive.setInitialState(self.m_idle)

        # Lightning strikes at random.
        self.m_alive.addTransition(LightningStrikesTransition(lightningBlink))
        lightningBlink.addTransition(timer.timeout, self.m_dead)

        self.m_machine.setInitialState(self.m_alive)

    def setDeathAnimation(self, fileName):
        deathAnimation = self.makeState(self.m_dead, fileName)
        self.m_dead.setInitialState(deathAnimation)

    def start(self):
        self.m_machine.start()

    def addActivity(self, fileName, key):
        state = self.makeState(self.m_alive, fileName)
        self.m_alive.addTransition(KeyPressTransition(self.m_keyReceiver, key, state))

    def makeState(self, parentState, animationFileName):
        topLevel = QState(parentState)

        animation = Animation()

        file = QFile(animationFileName)
        if file.open(QIODevice.ReadOnly):
            animation.load(file)

        frameCount = animation.totalFrames()
        previousState = None
        for i in range(frameCount):
            animation.setCurrentFrame(i)

            frameState = QState(topLevel)
            nodeCount = animation.nodeCount()
            for j in range(nodeCount):
                frameState.assignProperty(self.m_stickMan.node(j), "pos", animation.nodePos(j))

            frameState.setObjectName("frame %d" % i)

            if previousState is None:
                topLevel.setInitialState(frameState)
            else:
                previousState.addTransition(previousState.propertiesAssigned, frameState)

            previousState = frameState

        previousState.addTransition(previousState.propertiesAssigned, topLevel.initialState())

        return topLevel
Пример #6
0
    def loadState(self, dev, stateParam, stateID = ""):

        curExecContext = ScExecContext()
        curExecContext.stateMachine = self.stateMachine
        curHistoryState = None
        debug = True

        r = QXmlStreamReader(dev)

        while not r.atEnd():
            r.readNext()
            if r.isStartElement():
                logger.info("Element :<%s>", r.name())
                #
                # <scxml>
                #
                name = r.name().lower()
                if name == "scxml":

                    if stateID == "":
                        topLevelState = curState = stateParam
                        self.stateInfo[curState] = r.attributes().value("initial")
                        if curState == self.stateMachine:
                            pass
                #
                # <state> || <parallel>
                #
                elif name == "state" or name == "parallel":
                    inRoot = False
                    stateId = r.attributes().value("id")
                    newState = None
                    #
                    # Create state
                    #
                    if curState is not None:
                        logger.info("Creating state [%s] child of [%s]", stateId, curState.objectName())
                        type = QState.ExclusiveStates if name == "state" else QState.ParallelStates
                        newState = QState(type, curState)
                    #
                    # ???
                    #
                    elif stateId == stateID:
                        topLevelState = newState = stateParam

                    if newState is not None:
                        self.stateInfo[newState] = r.attributes().value("initial")
                        newState.setObjectName(stateId)
                        #
                        # initial state
                        #
                        if stateId is not "" and self.stateInfo[curState] == stateId:
                            if curState == self.stateMachine:
                                logger.info("Setting [%s] initial state to [%s]",
                                            self.stateMachine.objectName(),
                                            newState.objectName())
                                self.stateMachine.setInitialState(newState)
                            else:
                                logger.info("Setting [%s] initial state to [%s]",
                                            curState.objectName(),
                                            newState.objectName())
                                curState.setInitialState(newState)
                        #
                        # TODO implement src attribute management in state element
                        #
                        initialID = r.attributes().value("initial")
                        self.stateByID[stateId] = newState
                        curState = newState
                        curExecContext.state = newState

                        if debug:

                            # Add entry and exit log

                            curExecContext.script = 'logger.debug("[scxml] [debug] > Entering state: [' + stateId + ']")'
                            curExecContext.type = ScExecContext.StateEntry
                            curExecContext.applyScript()
                            curExecContext.script = 'logger.debug("[scxml] [debug] < Exiting state: [' + stateId + ']")'
                            curExecContext.type = ScExecContext.StateExit
                            curExecContext.applyScript()
                #
                # <initial>
                #
                elif name == "initial":
                    if curState is not None and self.stateInfo[curState] == "":
                        logger.info("Creating state [%s] child of [%s]", stateId, curState.objectName())
                        newState = QState(curState)
                        curState.setInitialState(newState)
                #
                # <history>
                #
                elif name == "history":
                    if curState is not None:
                        stateId = r.attributes().value("id")
                        type = r.attributes().value("type")
                        type = QHistoryState.ShallowHistory if type == "shallow" else QHistoryState.DeepHistory
                        curHistoryState = QHistoryState(type)
                        curHistoryState.setObjectName(stateId)
                        self.stateByID[stateId] = curHistoryState
                #
                # <final>
                #
                elif name == "final":
                    if curState is not None:
                        stateId = r.attributes().value("id")
                        f = QFinalState(curState)
                        f.setObjectName(stateId)
                        curExecContext.state = f
                        self.statesWithFinal.add(curState)
                        gp = curState.parentState()
                        if gp is not None:
                            if gp.childMode() == QState.ParallelStates:
                                self.statesWithFinal.add()
                        self.stateByID[stateId] = f

                        if debug:

                            # Add entry and exit log

                            curExecContext.script = 'logger.debug("[scxml] [debug] > Entering final state: [' + stateId + ']")'
                            curExecContext.type = ScExecContext.StateEntry
                            curExecContext.applyScript()
                            curExecContext.script = 'logger.debug("[scxml] [debug] < Exiting final state: [' + stateId + ']")'
                            curExecContext.type = ScExecContext.StateExit
                            curExecContext.applyScript()

                #
                # <script>
                #
                elif name == "script":
                    txt = r.readElementText()
                    #
                    # The SCXML Processor MUST evaluate any <script> element that is a child
                    # of <scxml> at document load time
                    #
                    if curExecContext.type == ScExecContext.Unknown and curState == topLevelState:
                        # TODO execute script
                        pass
                    else:
                        curExecContext.script += txt
                #
                # <log>
                #
                elif name == "log":
                    curExecContext.script += 'logger.' + r.attributes().value("level") + '("[' + \
                                             r.attributes().value("label") + '] [' +  \
                                             r.attributes().value("level") + '] ' + r.attributes().value("expr") + '")'
                #
                # <assign>
                #
                elif name == "assign":
                    pass
                #
                # <if>
                #
                elif name == "if":
                    pass
                #
                # <elseif>
                #
                elif name == "elseif":
                    pass
                #
                # <else>
                #
                elif name == "else":
                    pass
                #
                # <cancel>
                #
                elif name == "cancel":
                    pass
                #
                # <onentry>
                #
                elif name == "onentry":
                    curExecContext.type = ScExecContext.StateEntry
                    curExecContext.script = ""
                #
                # <onexit>
                #
                elif name == "onexit":
                    curExecContext.type = ScExecContext.StateExit
                    curExecContext.script = ""
                #
                # <raise>
                #
                elif name == "raise":
                    pass
                #
                # <send>
                #
                elif name == "send":
                    pass
                #
                # <invoke>
                #
                elif name == "invoke":
                    pass
                #
                # <transition>
                #
                elif name == "transition":
                    if curHistoryState is not None:
                        inf = ScHistoryInfo()
                        inf.hstate = curHistoryState
                        inf.defaultStateID = r.attributes().value("target")
                        self.historyInfo.append(inf)
                    else:
                        inf = ScTransitionInfo()
                        inf.targets = r.attributes().value("target").split() # TODO split targets
                        curExecContext.type = ScExecContext.Transition

                        curExecContext.script = ""
                        if debug:
                            curExecContext.script = 'logger.debug("[scxml] [debug] = Transitioning to: [' \
                                                    + ', '.join(inf.targets) + ']")' + '\n'


                        curTransitions = list()
                        inf.transitions = list()
                        self.transitionsInf.append(inf)

                        for pfx in r.attributes().value("event").split(' '):
                            sigTransition = None
                            if pfx == '':

                                # For eventless transition create QScxmlEventlessTransition transition

                                sigTransition = QScxmlEventlessTransition(self.stateMachine)

                            elif pfx.startswith("q-signal:"):

                                # For all q-signal event, add a QSxcmlSignalTransition

                                self.signalEvents.append(pfx)

                                # get object name (a.b.c) => a

                                objName = pfx[pfx.index(':')+1:pfx.index('.')]

                                # get object reference

                                obj = self.stateMachine.registeredObjects[objName]

                                # get signal reference

                                for attr in pfx[pfx.index('.')+1:].split('.'):
                                    sig = getattr(obj, attr)
                                    obj = sig

                                # create Signal transition

                                sigTransition = QScxmlSignalTransition(sig, self.stateMachine)

                            if sigTransition is not None:

                                # add condition to transition

                                sigTransition.setConditionExpression(r.attributes().value("cond"))

                                # add transition to current state

                                curState.addTransition(sigTransition)

                                # append sigTransition to transition info

                                inf.transitions.append(sigTransition)

                                # append sigTransition to curTransitions list

                                curTransitions.append(sigTransition)

                            else:
                                logger.error("Transition creation error")
            #
            # End element
            #
            elif r.isEndElement():
                name = r.name().lower()
                #
                # </state> or </parallel>
                #
                if name == "state" or name == "parallel":
                    if curState == topLevelState:
                        return
                    else:
                        curState = curState.parent()
                        curExecContext.state = curState
                #
                # </history>
                #
                elif name == "history":
                    curHistoryState = None
                #
                # </final>
                #
                elif name == "final":
                    curExecContext.state = curExecContext.state.parentState()
                #
                # </if>
                #
                elif name == "if":
                    pass
                #
                # </send> </raise>
                #
                elif name == "send" or name == "raise":
                    pass
                #
                # </onentry> </onexit> </scxml>
                #
                elif name == "onentry" or name == "onexit" or name == "scxml":
                    curExecContext.state = curState
                    curExecContext.type = ScExecContext.StateExit if name == "onexit" else ScExecContext.StateEntry
                    curExecContext.applyScript()
                    curExecContext.type = ScExecContext.Unknown
                    curExecContext.script = ""
                #
                # </transition>
                #
                elif name == "transition":
                    if curHistoryState is None:
                        curExecContext.transitions = curTransitions
                        curExecContext.type = ScExecContext.Transition
                        curExecContext.applyScript()
                        curExecContext.script = ""
                    curExecContext.type = ScExecContext.Unknown