package org.flixel.system.debug;
import org.flixel.FlxG;
import org.flixel.FlxU;
import org.flixel.system.gdx.text.GdxTextField;
import com.badlogic.gdx.files.FileHandle;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
/**
* This class contains the record, stop, play, and step 1 frame buttons seen on the top edge of the debugger overlay.
*
* @author Thomas Weston
*/
public class VCR
{
protected String ImgOpen = "../../data/vcr/open.png";
protected String ImgRecordOff = "../../data/vcr/record_off.png";
protected String ImgRecordOn = "../../data/vcr/record_on.png";
protected String ImgStop = "../../data/vcr/stop.png";
protected String ImgFlixel = "../../data/vcr/flixel.png";
protected String ImgRestart = "../../data/vcr/restart.png";
protected String ImgPause = "../../data/vcr/pause.png";
protected String ImgPlay = "../../data/vcr/play.png";
protected String ImgStep = "../../data/vcr/step.png";
//static protected final FILE_TYPES:Array = [new FileFilter("Flixel Game Recording", "*.fgr")];
static protected final String DEFAULT_FILE_NAME = "replay.fgr";
/**
* Whether the debugger has been paused.
*/
public boolean paused;
/**
* Whether a "1 frame step forward" was requested.
*/
public boolean stepRequested;
//protected var _open:Bitmap;
//protected var _recordOff:Bitmap;
//protected var _recordOn:Bitmap;
//protected var _stop:Bitmap;
//protected var _flixel:Bitmap;
//protected var _restart:Bitmap;
//protected var _pause:Bitmap;
//protected var _play:Bitmap;
//protected var _step:Bitmap;
protected boolean _overOpen;
protected boolean _overRecord;
protected boolean _overRestart;
protected boolean _overPause;
protected boolean _overStep;
protected boolean _pressingOpen;
protected boolean _pressingRecord;
protected boolean _pressingRestart;
protected boolean _pressingPause;
protected boolean _pressingStep;
protected FileHandle _file;
protected TextField _runtimeDisplay;
protected int _runtime;
/**
* Creates the "VCR" control panel for debugger pausing, stepping, and recording.
*/
public VCR()
{
super();
//int spacing = 7;
//_open = new ImgOpen();
//addChild(_open);
//_recordOff = new ImgRecordOff();
//_recordOff.x = _open.x + _open.width + spacing;
//addChild(_recordOff);
//_recordOn = new ImgRecordOn();
//_recordOn.x = _recordOff.x;
//_recordOn.visible = false;
//addChild(_recordOn);
//_stop = new ImgStop();
//_stop.x = _recordOff.x;
//_stop.visible = false;
//addChild(_stop);
//_flixel = new ImgFlixel();
//_flixel.x = _recordOff.x + _recordOff.width + spacing;
//addChild(_flixel);
//_restart = new ImgRestart();
//_restart.x = _flixel.x + _flixel.width + spacing;
//addChild(_restart);
//_pause = new ImgPause();
//_pause.x = _restart.x + _restart.width + spacing;
//addChild(_pause);
//_play = new ImgPlay();
//_play.x = _pause.x;
//_play.visible = false;
//addChild(_play);
//_step = new ImgStep();
//_step.x = _pause.x + _pause.width + spacing;
//addChild(_step);
_runtimeDisplay = new GdxTextField();
//_runtimeDisplay.width = width;
//_runtimeDisplay.x = width;
_runtimeDisplay.y = -2;
//_runtimeDisplay.multiline = false;
//_runtimeDisplay.wordWrap = false;
//_runtimeDisplay.selectable = false;
_runtimeDisplay.defaultTextFormat = new TextFormat("Courier",12,0xffffff,false,false,false,null,null,"center");
//_runtimeDisplay.visible = false;
//addChild(_runtimeDisplay);
_runtime = 0;
stepRequested = false;
_file = null;
unpress();
checkOver();
updateGUI();
//addEventListener(Event.ENTER_FRAME,init);
}
/**
* Clean up memory.
*/
public void destroy()
{
_file = null;
//removeChild(_open);
//_open = null;
//removeChild(_recordOff);
//_recordOff = null;
//removeChild(_recordOn);
//_recordOn = null;
//removeChild(_stop);
//_stop = null;
//removeChild(_flixel);
//_flixel = null;
//removeChild(_restart);
//_restart = null;
//removeChild(_pause);
//_pause = null;
//removeChild(_play);
//_play = null;
//removeChild(_step);
//_step = null;
//parent.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
//parent.removeEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
//parent.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
}
/**
* Usually called by FlxGame when a requested recording has begun.
* Just updates the VCR GUI so the buttons are in the right state.
*/
public void recording()
{
//_stop.visible = false;
//_recordOff.visible = false;
//_recordOn.visible = true;
}
/**
* Usually called by FlxGame when a replay has been stopped.
* Just updates the VCR GUI so the buttons are in the right state.
*/
public void stopped()
{
//_stop.visible = false;
//_recordOn.visible = false;
//_recordOff.visible = true;
}
/**
* Usually called by FlxGame when a requested replay has begun.
* Just updates the VCR GUI so the buttons are in the right state.
*/
public void playing()
{
//_recordOff.visible = false;
//_recordOn.visible = false;
//_stop.visible = true;
}
/**
* Just updates the VCR GUI so the runtime displays roughly the right thing.
*/
public void updateRuntime(int Time)
{
_runtime += Time;
_runtimeDisplay.setText(FlxU.formatTime(_runtime/1000f,true));
//if(!_runtimeDisplay.visible)
// _runtimeDisplay.visible = true;
}
//*** ACTUAL BUTTON BEHAVIORS ***//
/**
* Called when the "open file" button is pressed.
* Opens the file dialog and registers event handlers for the file dialog.
*/
public void onOpen()
{
//_file = Gdx.files.external(path);
//_file.addEventListener(Event.SELECT, onOpenSelect);
//_file.addEventListener(Event.CANCEL, onOpenCancel);
//_file.browse(FILE_TYPES);
}
/**
* Called when a file is picked from the file dialog.
* Attempts to load the file and registers file loading event handlers.
*
* @param E Flash event.
*/
protected void onOpenSelect(Event E)
{
//_file.removeEventListener(Event.SELECT, onOpenSelect);
//_file.removeEventListener(Event.CANCEL, onOpenCancel);
//_file.addEventListener(Event.COMPLETE, onOpenComplete);
//_file.addEventListener(IOErrorEvent.IO_ERROR, onOpenError);
//_file.load();
}
/**
* Called when a file is opened successfully.
* If there's stuff inside, then the contents are loaded into a new replay.
*
* @param E Flash Event.
*/
protected void onOpenComplete(Event E)
{
//_file.removeEventListener(Event.COMPLETE, onOpenComplete);
//_file.removeEventListener(IOErrorEvent.IO_ERROR, onOpenError);
//Turn the file into a giant string
String fileContents = null;
//var data:ByteArray = _file.data;
//if(data != null)
// fileContents = data.readUTFBytes(data.bytesAvailable);
_file = null;
if((fileContents == null) || (fileContents.length() <= 0))
{
FlxG.log("ERROR: Empty flixel gameplay record.");
return;
}
//FlxG.loadReplay(fileContents);
}
/**
* Called if the open file dialog is canceled.
*
* @param E Flash Event.
*/
protected void onOpenCancel(Event E)
{
//_file.removeEventListener(Event.SELECT, onOpenSelect);
//_file.removeEventListener(Event.CANCEL, onOpenCancel);
_file = null;
}
/**
* Called if there is a file open error.
*
* @param E Flash Event.
*/
protected void onOpenError(Event E)
{
//_file.removeEventListener(Event.COMPLETE, onOpenComplete);
//_file.removeEventListener(IOErrorEvent.IO_ERROR, onOpenError);
_file = null;
FlxG.log("ERROR: Unable to open flixel gameplay record.");
}
/**
* Called when the user presses the white record button.
* If Alt is pressed, the current state is reset, and a new recording is requested.
* If Alt is NOT pressed, the game is reset, and a new recording is requested.
*
* @param StandardMode Whether to reset the whole game, or just this <code>FlxState</code>. StandardMode == false is useful for recording demos or attract modes.
*/
public void onRecord(boolean StandardMode)
{
//if(_play.visible)
// onPlay();
FlxG.recordReplay(StandardMode);
}
/**
* Called when the user presses the white record button.
* If Alt is pressed, the current state is reset, and a new recording is requested.
* If Alt is NOT pressed, the game is reset, and a new recording is requested.
*/
public void onRecord()
{
onRecord(false);
}
/**
* Called when the user presses the red record button.
* Stops the current recording, opens the save file dialog, and registers event handlers.
*/
public void stopRecording()
{
String data = FlxG.stopRecording();
if((data != null) && (data.length() > 0))
{
//_file = new FileReference();
//_file.addEventListener(Event.COMPLETE, onSaveComplete);
//_file.addEventListener(Event.CANCEL,onSaveCancel);
//_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
//_file.save(data, DEFAULT_FILE_NAME);
}
}
/**
* Called when the file is saved successfully.
*
* @param E Flash Event.
*/
protected void onSaveComplete(Event E)
{
//_file.removeEventListener(Event.COMPLETE, onSaveComplete);
//_file.removeEventListener(Event.CANCEL,onSaveCancel);
//_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log("FLIXEL: successfully saved flixel gameplay record.");
}
/**
* Called when the save file dialog is cancelled.
*
* @param E Flash Event.
*/
protected void onSaveCancel(Event E)
{
//_file.removeEventListener(Event.COMPLETE, onSaveComplete);
//_file.removeEventListener(Event.CANCEL,onSaveCancel);
//_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
}
/**
* Called if there is an error while saving the gameplay recording.
*
* @param E Flash Event.
*/
protected void onSaveError(Event E)
{
//_file.removeEventListener(Event.COMPLETE, onSaveComplete);
//_file.removeEventListener(Event.CANCEL,onSaveCancel);
//_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log("ERROR: problem saving flixel gameplay record.");
}
/**
* Called when the user presses the stop button.
* Stops the current replay.
*/
public void onStop()
{
FlxG.stopReplay();
}
/**
* Called when the user presses the Rewind-looking button.
* If Alt is pressed, the entire game is reset.
* If Alt is NOT pressed, only the current state is reset.
* The GUI is updated accordingly.
*
* @param StandardMode Whether to reset the current game (== true), or just the current state. Just resetting the current state can be very handy for debugging.
*/
public void onRestart(boolean StandardMode)
{
FlxG.reloadReplay(StandardMode);
//if(false)
//{
// _recordOff.visible = false;
// _recordOn.visible = false;
// _stop.visible = true;
// }
}
/**
* Called when the user presses the Pause button.
* This is different from user-defined pause behavior, or focus lost behavior.
* Does NOT pause music playback!!
*/
public void onPause()
{
paused = true;
//_pause.visible = false;
//_play.visible = true;
}
/**
* Called when the user presses the Play button.
* This is different from user-defined unpause behavior, or focus gained behavior.
*/
public void onPlay()
{
paused = false;
//_play.visible = false;
//_pause.visible = true;
}
/**
* Called when the user presses the fast-forward-looking button.
* Requests a 1-frame step forward in the game loop.
*/
public void onStep()
{
if(!paused)
onPause();
stepRequested = true;
}
//***EVENT HANDLERS***//
/**
* Just sets up basic mouse listeners, a la FlxWindow.
*
* @param E Flash event.
*/
protected void init(Event E)
{
//if(root == null)
// return;
//removeEventListener(Event.ENTER_FRAME,init);
//parent.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
//parent.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
//parent.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
}
/**
* If the mouse moves, check to see if any buttons should be highlighted.
*
* @param E Flash mouse event.
*/
protected void onMouseMove(MouseEvent E)
{
if(!checkOver())
unpress();
updateGUI();
}
/**
* If the mouse is pressed down, check to see if the user started pressing down a specific button.
*
* @param E Flash mouse event.
*/
protected void onMouseDown(MouseEvent E)
{
unpress();
if(_overOpen)
_pressingOpen = true;
if(_overRecord)
_pressingRecord = true;
if(_overRestart)
_pressingRestart = true;
if(_overPause)
_pressingPause = true;
if(_overStep)
_pressingStep = true;
}
/**
* If the mouse is released, check to see if it was released over a button that was pressed.
* If it was, take the appropriate action based on button state and visibility.
*
* @param E Flash mouse event.
*/
protected void onMouseUp(MouseEvent E)
{
if(_overOpen && _pressingOpen)
onOpen();
else if(_overRecord && _pressingRecord)
{
//if(_stop.visible)
// onStop();
//else if(_recordOn.visible)
// stopRecording();
//else
// onRecord(!E.altKey);
}
//else if(_overRestart && _pressingRestart)
// onRestart(!E.altKey);
else if(_overPause && _pressingPause)
{
//if(_play.visible)
// onPlay();
//else
// onPause();
}
else if(_overStep && _pressingStep)
onStep();
unpress();
checkOver();
updateGUI();
}
//***MISC GUI MGMT STUFF***//
/**
* This function checks to see what button the mouse is currently over.
* Has some special behavior based on whether a recording is happening or not.
*
* @return Whether the mouse was over any buttons or not.
*/
protected boolean checkOver()
{
_overOpen = _overRecord = _overRestart = _overPause = _overStep = false;
/*
* if((mouseX < 0) || (mouseX > width) || (mouseY < 0) || (mouseY > 15))
* return false; if((mouseX >= _recordOff.x) && (mouseX <= _recordOff.x
* + _recordOff.width)) _overRecord = true; if(!_recordOn.visible &&
* !_overRecord) { if((mouseX >= _open.x) && (mouseX <= _open.x +
* _open.width)) _overOpen = true; else if((mouseX >= _restart.x) &&
* (mouseX <= _restart.x + _restart.width)) _overRestart = true; else
* if((mouseX >= _pause.x) && (mouseX <= _pause.x + _pause.width))
* _overPause = true; else if((mouseX >= _step.x) && (mouseX <= _step.x
* + _step.width)) _overStep = true; }
*/
return true;
}
/**
* Sets all the pressed state variables for the buttons to false.
*/
protected void unpress()
{
_pressingOpen = false;
_pressingRecord = false;
_pressingRestart = false;
_pressingPause = false;
_pressingStep = false;
}
/**
* Figures out what buttons to highlight based on the _overWhatever and _pressingWhatever variables.
*/
protected void updateGUI()
{
//if(_recordOn.visible)
//{
// _open.alpha = _restart.alpha = _pause.alpha = _step.alpha = 0.35;
// _recordOn.alpha = 1.0;
// return;
//}
//if(_overOpen && (_open.alpha != 1.0))
// _open.alpha = 1.0;
//else if(!_overOpen && (_open.alpha != 0.8))
// _open.alpha = 0.8;
//if(_overRecord && (_recordOff.alpha != 1.0))
// _recordOff.alpha = _recordOn.alpha = _stop.alpha = 1.0;
//else if(!_overRecord && (_recordOff.alpha != 0.8))
// _recordOff.alpha = _recordOn.alpha = _stop.alpha = 0.8;
//if(_overRestart && (_restart.alpha != 1.0))
// _restart.alpha = 1.0;
//else if(!_overRestart && (_restart.alpha != 0.8))
// _restart.alpha = 0.8;
//if(_overPause && (_pause.alpha != 1.0))
// _pause.alpha = _play.alpha = 1.0;
//else if(!_overPause && (_pause.alpha != 0.8))
// _pause.alpha = _play.alpha = 0.8;
//if(_overStep && (_step.alpha != 1.0))
// _step.alpha = 1.0;
//else if(!_overStep && (_step.alpha != 0.8))
// _step.alpha = 0.8;
}
}