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
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
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()
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
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
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