Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // fsStateMachine.m
- // fuzzspaces
- //
- // Created by fuzzimac4 on 6/4/09.
- // Copyright 2009 __MyCompanyName__. All rights reserved.
- //
- #import "fsStateMachine.h"
- #include "sio2.h"
- // State register offset table
- unsigned short fsStateRegisterOffset[] = {FS_STATE_REGISTER_ENVIRONMENT,
- FS_STATE_REGISTER_MENU,
- FS_STATE_REGISTER_TOOL,
- FS_STATE_REGISTER_VIEW,
- FS_STATE_REGISTER_TOUCH,
- FS_STATE_REGISTER_MULTITOUCH,
- 0x00};
- @implementation fsStateMachine
- @synthesize touchAccumulator;
- @synthesize touchTimer;
- @synthesize touchPositions;
- @synthesize touch2Positions;
- - (fsStateMachine *) init {
- self = [super init];
- inputState = (fsInputState *) calloc(1, sizeof(fsInputState));
- touchTimer = nil;
- touchPositions = (vec2 *) calloc(1, sizeof(vec2) * FS_TOUCH_LAST_POSITIONS);
- touch2Positions = (vec2 *) calloc(1, sizeof(vec2) * FS_TOUCH_LAST_POSITIONS);
- currentStateCallback = NULL;
- mainRunLoop = [NSRunLoop currentRunLoop];
- [self setState:FS_STATE_START inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_NO_SELECTION inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_VIEW_PAN inRegister:FS_STATE_REGISTER_VIEW];
- return self;
- }
- - (void) dealloc {
- free(inputState);
- free(touchPositions);
- free(touch2Positions);
- inputState = NULL;
- touchPositions = NULL;
- touch2Positions = NULL;
- [super dealloc];
- }
- - (unsigned short *) registerOffsetFor:(unsigned short)stateRegister {
- unsigned short *baseOffset = fsStateRegisterOffset;
- unsigned short *currentOffset = fsStateRegisterOffset;
- while (*currentOffset) {
- if (*currentOffset == stateRegister)
- return (unsigned short *) (++currentOffset - baseOffset);
- currentOffset++;
- }
- return NULL;
- }
- - (void) setState:(unsigned short)stateFlag inRegister:(unsigned short)stateRegister {
- unsigned short *registerPtr = [self registerOffsetFor:stateRegister];
- registerPtr = (unsigned short *) ((unsigned int) inputState + (unsigned int) registerPtr);
- *registerPtr = *registerPtr | stateFlag;
- }
- - (void) resetState:(unsigned short)stateFlag inRegister:(unsigned short)stateRegister {
- unsigned short *registerPtr = [self registerOffsetFor:stateRegister];
- registerPtr = (unsigned short *) ((unsigned int) inputState + (unsigned int) registerPtr);
- *registerPtr = *registerPtr & ~stateFlag;
- }
- - (void) resetRegister:(unsigned short)stateRegister {
- unsigned short *registerPtr = [self registerOffsetFor:stateRegister];
- registerPtr = (unsigned short *) ((unsigned int) inputState + (unsigned int) registerPtr);
- *registerPtr = 0x0;
- }
- - (BOOL) isState:(unsigned short)stateFlag inRegister:(unsigned short)stateRegister {
- unsigned short *registerPtr = [self registerOffsetFor:stateRegister];
- registerPtr = (unsigned short *) ((unsigned int) inputState + (unsigned int) registerPtr);
- return (*registerPtr & stateFlag) != 0;
- }
- - (void) applyStateDiff:(fsInputStateDiff *)stateDiff {
- // First, test the registers to make sure we can switch to the new input state
- if (stateDiff->testStates.registerEnvironment) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_ENVIRONMENT])
- return;
- }
- if (stateDiff->testStates.registerMenu) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_MENU])
- return;
- }
- if (stateDiff->testStates.registerTool) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_TOOL])
- return;
- }
- if (stateDiff->testStates.registerView) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_VIEW])
- return;
- }
- if (stateDiff->testStates.registerTouch) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_TOUCH])
- return;
- }
- if (stateDiff->testStates.registerMultitouch) {
- if (![self isState:stateDiff->testStates.registerEnvironment inRegister:FS_STATE_REGISTER_MULTITOUCH])
- return;
- }
- // Second, clear any registers that were set
- if (FS_STATE_REGISTER_ENVIRONMENT & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_ENVIRONMENT];
- if (FS_STATE_REGISTER_MENU & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_MENU];
- if (FS_STATE_REGISTER_TOOL & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_TOOL];
- if (FS_STATE_REGISTER_VIEW & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_VIEW];
- if (FS_STATE_REGISTER_TOUCH & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_TOUCH];
- if (FS_STATE_REGISTER_MULTITOUCH & stateDiff->clearRegisters)
- [self resetRegister:FS_STATE_REGISTER_MULTITOUCH];
- // Next, unset any states
- [self resetState:stateDiff->unsetStates.registerEnvironment inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- [self resetState:stateDiff->unsetStates.registerMenu inRegister:FS_STATE_REGISTER_MENU];
- [self resetState:stateDiff->unsetStates.registerTool inRegister:FS_STATE_REGISTER_TOOL];
- [self resetState:stateDiff->unsetStates.registerView inRegister:FS_STATE_REGISTER_VIEW];
- [self resetState:stateDiff->unsetStates.registerTouch inRegister:FS_STATE_REGISTER_TOUCH];
- [self resetState:stateDiff->unsetStates.registerMultitouch inRegister:FS_STATE_REGISTER_MULTITOUCH];
- // Finally, set any new states
- [self setState:stateDiff->setStates.registerEnvironment inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:stateDiff->setStates.registerMenu inRegister:FS_STATE_REGISTER_MENU];
- [self setState:stateDiff->setStates.registerTool inRegister:FS_STATE_REGISTER_TOOL];
- [self setState:stateDiff->setStates.registerView inRegister:FS_STATE_REGISTER_VIEW];
- [self setState:stateDiff->setStates.registerTouch inRegister:FS_STATE_REGISTER_TOUCH];
- [self setState:stateDiff->setStates.registerMultitouch inRegister:FS_STATE_REGISTER_MULTITOUCH];
- }
- // Convention is to reset registers, then states, and finally set states.
- - (void) updateTouchesForWindow:(SIO2window *)_SIO2window {
- [self setTouchAccumulator: _SIO2window->n_tap];
- switch (_SIO2window->n_touch) {
- case 0:
- [self.touchTimer invalidate];
- self.touchTimer = nil;
- [self resetRegister:FS_STATE_REGISTER_TOUCH];
- [self resetRegister:FS_STATE_REGISTER_MULTITOUCH];
- [self resetState:
- FS_STATE_SCREEN_TOUCH | FS_STATE_SCREEN_MULTITOUCH
- inRegister:
- FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_START inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- break;
- case 1:
- [self resetRegister:FS_STATE_REGISTER_MULTITOUCH];
- [self resetState:
- FS_STATE_START | FS_STATE_SCREEN_MULTITOUCH
- inRegister:
- FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_SCREEN_TOUCH inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- self.touchTimer = [NSTimer timerWithTimeInterval:FS_TOUCH_IS_HELD_AFTER
- target:self
- selector:@selector(touchWasHeld:)
- userInfo:nil
- repeats:false];
- [mainRunLoop addTimer:self.touchTimer forMode:NSDefaultRunLoopMode];
- break;
- case 2:
- [self.touchTimer invalidate];
- self.touchTimer = nil;
- [self resetRegister:FS_STATE_REGISTER_TOUCH];
- [self resetState:
- FS_STATE_START | FS_STATE_SCREEN_TOUCH
- inRegister:
- FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_SCREEN_MULTITOUCH inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- break;
- default:
- [self resetRegister:FS_STATE_REGISTER_TOUCH];
- [self resetRegister:FS_STATE_REGISTER_MULTITOUCH];
- [self resetState:
- FS_STATE_SCREEN_TOUCH | FS_STATE_SCREEN_MULTITOUCH | FS_STATE_START
- inRegister:
- FS_STATE_REGISTER_ENVIRONMENT];
- [self setState:FS_STATE_ERROR inRegister:FS_STATE_REGISTER_ENVIRONMENT];
- break;
- }
- }
- - (void) touchWasHeld:(NSTimer *)touchTimer {
- [self.touchTimer invalidate];
- self.touchTimer = nil;
- [self setState:FS_STATE_SCREEN_TOUCH_HOLD inRegister:FS_STATE_REGISTER_TOUCH];
- }
- - (void) updateWithMoveForWindow:(SIO2window *)_SIO2window {
- return;
- }
- - (void) updateWithAccelerometer:(SIO2window *)_SIO2window {
- return;
- }
- - (BOOL) areToolsInMenuEnabled {
- return true;
- }
- @end
Add Comment
Please, Sign In to add comment