package com.badlogic.gdx.automation.recorder; import java.io.IOException; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.automation.recorder.EventBufferAccessHelper.KeyEvent; import com.badlogic.gdx.automation.recorder.EventBufferAccessHelper.PointerEvent; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.Accelerometer; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.Button; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.KeyPressed; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.Orientation; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.Pointer; import com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.Type; import com.badlogic.gdx.automation.recorder.io.InputRecordWriter; /** * A class to be fed InputStates via {@link #process(InputState)} so it can * process them and write it using {@link InputRecorder#getRecordWriter()} * * @author Lukas Böhm */ class InputStateProcessor { private final InputRecorder recorder; private InputState lastState = null; private long timeDelta; private final int copiedValuesFlag; private final int trackedValuesFlag; public InputStateProcessor(InputRecorder recorder) { this.recorder = recorder; int flags = 0; InputRecorderConfiguration config = recorder.getConfiguration(); if (config.recordButtons) { flags |= Type.BUTTONS.key; } if (config.recordOrientation) { flags |= Type.ORIENTATION.key; } if (config.recordPointers) { flags |= Type.POINTERS.key; } if (config.recordPointerEvents) { flags |= Type.POINTER_EVENTS.key; } copiedValuesFlag = flags; if (config.recordKeyEvents) { flags |= Type.KEY_EVENTS.key; } if (config.recordKeysPressed) { flags |= Type.KEYS_PRESSED.key; } trackedValuesFlag = flags; } private long getTimeDelta() { long delta = timeDelta; timeDelta = 0; return delta; } /** * Compares the last state given to the processor with the given one and * writes the differences using the {@link InputRecorder}'s * {@link InputRecordWriter} * * @param state */ public void process(InputState state) throws IOException { timeDelta = lastState == null ? 0 : state.timeStamp - lastState.timeStamp; if ((trackedValuesFlag & Type.BUTTONS.key) != 0) { processButtons(state); } if ((trackedValuesFlag & Type.KEY_EVENTS.key) != 0) { processKeyEvents(state); } if ((trackedValuesFlag & Type.KEYS_PRESSED.key) != 0) { processKeysPressed(state); } if ((trackedValuesFlag & Type.ORIENTATION.key) != 0) { processOrientation(state); } if ((trackedValuesFlag & Type.POINTERS.key) != 0) { processPointers(state); } if ((trackedValuesFlag & Type.POINTER_EVENTS.key) != 0) { processPointerEvents(state); } if (lastState == null) { lastState = new InputState( recorder.getConfiguration().recordedPointerCount); } lastState.set(state, copiedValuesFlag); lastState.timeStamp = state.timeStamp; } private void processButtons(InputState state) throws IOException { if (lastState == null || state.button0 != lastState.button0 || state.button1 != lastState.button1 || state.button2 != lastState.button2) { Button buttonChange = new Button(); buttonChange.button0 = state.button0; buttonChange.button1 = state.button1; buttonChange.button2 = state.button2; buttonChange.timeDelta = getTimeDelta(); recorder.getRecordWriter().writeSyncValues(buttonChange); } } private void processKeyEvents(InputState state) throws IOException { InputRecordWriter writer = recorder.getRecordWriter(); for (KeyEvent event : state.keyEvents) { com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.KeyEvent valueEvent = new com.badlogic.gdx.automation.recorder.InputProperty.SyncProperty.KeyEvent( event); valueEvent.timeDelta = getTimeDelta(); writer.writeSyncValues(valueEvent); } } private void processKeysPressed(InputState state) throws IOException { InputRecordWriter writer = recorder.getRecordWriter(); // look for newly pressed keys for (int key : state.pressedKeys.keySet()) { if (state.pressedKeys.get(key) && !lastState.pressedKeys.get(key)) { KeyPressed pressed = new KeyPressed(); pressed.keyCode = key; pressed.type = KeyPressed.Type.PRESS; pressed.timeDelta = getTimeDelta(); writer.writeSyncValues(pressed); } } // look for released keys for (int key : lastState.pressedKeys.keySet()) { if (lastState.pressedKeys.get(key) && !state.pressedKeys.get(key)) { KeyPressed pressed = new KeyPressed(); pressed.keyCode = key; pressed.type = KeyPressed.Type.RELEASE; pressed.timeDelta = getTimeDelta(); writer.writeSyncValues(pressed); } } } private void processOrientation(InputState state) { if (lastState == null || state.accelerometerX != lastState.accelerometerX || state.accelerometerY != lastState.accelerometerY || state.accelerometerZ != lastState.accelerometerZ) { Accelerometer accelChange = new Accelerometer(); accelChange.accelerometerX = state.accelerometerX; accelChange.accelerometerY = state.accelerometerY; accelChange.accelerometerZ = state.accelerometerZ; accelChange.timeDelta = getTimeDelta(); } if (lastState == null || state.roll != lastState.roll || state.pitch != lastState.pitch || state.azimuth != lastState.azimuth || state.orientation != lastState.orientation) { Orientation oChange = new Orientation(); oChange.pitch = state.pitch; oChange.roll = state.roll; oChange.azimuth = state.azimuth; oChange.orientation = state.orientation; System.arraycopy(state.rotationMatrix, 0, oChange.rotationMatrix, 0, 16); oChange.timeDelta = getTimeDelta(); } } private void processPointers(InputState state) throws IOException { int maxPtrs = recorder.getConfiguration().recordedPointerCount; InputRecordWriter writer = recorder.getRecordWriter(); if (recorder.getConfiguration().absoluteCoords) { for (int i = 0; i < maxPtrs; i++) { // TODO are the deltas really dependent on the coordinates? if (lastState == null || state.justTouched != lastState.justTouched || state.x[i] != lastState.x[i] || state.y[i] != lastState.y[i]) { Pointer ptrChange = new Pointer(); ptrChange.x = state.x[i]; ptrChange.y = state.y[i]; ptrChange.deltaX = state.deltaX[i]; ptrChange.deltaY = state.deltaY[i]; ptrChange.pointer = i; ptrChange.timeDelta = getTimeDelta(); writer.writeSyncValues(ptrChange); } } } else { int w = Gdx.graphics.getWidth(); int h = Gdx.graphics.getHeight(); for (int i = 0; i < maxPtrs; i++) { if (lastState == null || state.justTouched != lastState.justTouched || state.x[i] != lastState.x[i] || state.y[i] != lastState.y[i]) { Pointer ptrChange = new Pointer(); ptrChange.x = state.x[i] / w; ptrChange.y = state.y[i] / h; ptrChange.deltaX = state.deltaX[i] / w; ptrChange.deltaY = state.deltaY[i] / h; ptrChange.pointer = i; ptrChange.timeDelta = getTimeDelta(); writer.writeSyncValues(ptrChange); } } } } private void processPointerEvents(InputState state) throws IOException { InputRecordWriter writer = recorder.getRecordWriter(); if (recorder.getConfiguration().absoluteCoords) { for (PointerEvent event : state.pointerEvents) { SyncProperty.PointerEvent ptrEvent = new SyncProperty.PointerEvent( event); ptrEvent.timeDelta = getTimeDelta(); writer.writeSyncValues(ptrEvent); } } else { int w = Gdx.graphics.getWidth(); int h = Gdx.graphics.getHeight(); for (PointerEvent event : state.pointerEvents) { SyncProperty.PointerEvent ptrEvent = new SyncProperty.PointerEvent( event); ptrEvent.x /= w; ptrEvent.y /= h; ptrEvent.timeDelta = getTimeDelta(); writer.writeSyncValues(ptrEvent); } } } /** * Resets the processor so it thinks that the next {@link InputState} given * to process is the first one ever recorded. */ public void reset() { lastState = null; } }