예제 #1
0
int main()
{
    StateMachine stateMachine;

    stateMachine.setOnStartCallback([] () { std::cout << "state machine started" << std::endl; });
    stateMachine.setOnStopCallback([] () { std::cout << "state machine stopped" << std::endl; });

    State* state1 = new State();
    state1->setOnEnterCallback([] (const Event*) { std::cout << "entering state1" << std::endl; });
    state1->setOnExitCallback([] (const Event*) { std::cout << "exiting state1" << std::endl; });

    State* state2 = new State();
    state2->setOnEnterCallback([] (const Event*) { std::cout << "entering state2" << std::endl; });
    state2->setOnExitCallback([] (const Event*) { std::cout << "exiting state2" << std::endl; });

    State* state3 = new State();
    state3->setOnEnterCallback([] (const Event*) { std::cout << "entering state3" << std::endl; });
    state3->setOnExitCallback([] (const Event*) { std::cout << "exiting state3" << std::endl; });

    stateMachine.addTransition(12, state1, state2);
    stateMachine.addTransition(13, state1, state3);
    stateMachine.addTransition(23, state2, state3);
    stateMachine.addTransition(31, state3, state1);
    stateMachine.setInitialState(state1);

    stateMachine.start();

    stateMachine.postEvent(new Event(12));
    stateMachine.postEvent(new Event(23));
    stateMachine.postEvent(new Event(31));
    stateMachine.postEvent(new Event(13));

    return 0;
}
예제 #2
0
GEP_UNITTEST_TEST(StateMachine, UpdateStepBehavior)
{
    GEP_UNITTEST_SETUP_EVENT_GLOBALS;
    auto& logging =
        TestLogging::instance();
    //DummyLogging::instance();

    // set up update framework
    _updateFramework.setElapsedTime(10.0f);

    // Add at least one callback so we know that we are still updating
    size_t frameCount = 0;
    _updateFramework.registerUpdateCallback([&](float){ logging.logWarning("frame %u:", frameCount); });

    StateMachineFactory factory(&g_stdAllocator);

    StateMachine* pMainFsm = nullptr;

    // Test data.

    size_t conditionCheckCount = 0;
    size_t updateCount = 0;

    // Actual tests. Don't put test data in here that has to be referenced
    // by the state machines, as they will get out of scope when pMainFsm
    // is actually run.
    {
        pMainFsm = factory.create("fsm");
        pMainFsm->setLogging(&logging);

        auto pState_A = pMainFsm->create<State>("A");
        auto pState_B = pMainFsm->create<State>("B");
        auto pState_C = pMainFsm->create<State>("C");

        pState_C->setLeaveCondition([](){ return true; });

        // Adding state transitions
        pMainFsm->addTransition("__enter", "A");
        pMainFsm->addTransition("A", "B", [&](){
            // This should be hit
            conditionCheckCount++;
            return true;
        });
        pMainFsm->addTransition("B", "C", [&](){
            // This should not be hit
            conditionCheckCount++;
            return true;
        });
        pMainFsm->addTransition("C", "__leave");

        pState_B->getLeaveEvent()->registerListener([&](State::LeaveEventData* pData){
            GEP_ASSERT(conditionCheckCount == 1, "Condition check 'A->B' not performed!");
            conditionCheckCount = 0;
            pData->setNextState(pState_C);
            return gep::EventResult::Handled;
        });

        pState_C->getLeaveEvent()->registerListener([&](State::LeaveEventData*){
            GEP_ASSERT(conditionCheckCount == 0, "Condition check 'B->C' should not have been performed!");
            conditionCheckCount = 0;
            return gep::EventResult::Handled;
        });

        // Set update event listeners. They should use the UpdateStepBehavior options.
        //////////////////////////////////////////////////////////////////////////

        pState_A->getUpdateEvent()->registerListener([&](State::UpdateEventData* pData){
            pData->setUpdateStepBehavior(State::UpdateStepBehavior::Leave);
            updateCount++;
            return gep::EventResult::Handled;
        });

        pState_B->getUpdateEvent()->registerListener([&](State::UpdateEventData* pData){
            pData->setUpdateStepBehavior(State::UpdateStepBehavior::LeaveWithNoConditionChecks);
            return gep::EventResult::Handled;
        });
    }

    pMainFsm->setLogging(&logging);

    // Run the machine
    pMainFsm->run(_updateFramework);

    for(frameCount = 0; frameCount < 5; ++frameCount)
    {
        _updateFramework.run();
    }

    GEP_ASSERT(updateCount > 0, "State A should have at least be updated once!");
}