1877 lines
54 KiB
C++
1877 lines
54 KiB
C++
|
#include "GameStateEditor.h"
|
||
|
#include "RoomPicker.h"
|
||
|
#include "RoomEditor.h"
|
||
|
#include "ScenePicker.h"
|
||
|
#include "TilePicker.h"
|
||
|
#include "StateObjectPicker.h"
|
||
|
#include "StateObjectEditor.h"
|
||
|
#include "DragAndDropManager.h"
|
||
|
#include "BorderPanel.h"
|
||
|
#include "labels.h"
|
||
|
#include "SpriteResource.h"
|
||
|
#include "packSaver.h"
|
||
|
#include "ToolTipManager.h"
|
||
|
|
||
|
|
||
|
#include "minorGems/util/TranslationManager.h"
|
||
|
|
||
|
#include "minorGems/util/log/AppLog.h"
|
||
|
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
|
||
|
extern StateObjectPicker *mainStateObjectPicker;
|
||
|
extern RoomPicker *mainRoomPicker;
|
||
|
extern RoomEditor *mainRoomEditor;
|
||
|
extern ScenePicker *mainScenePicker;
|
||
|
extern TilePicker *mainTilePicker;
|
||
|
|
||
|
extern StateObjectEditor *mainStateObjectEditor;
|
||
|
|
||
|
extern DragAndDropManager *mainDragAndDrop;
|
||
|
|
||
|
|
||
|
extern int gameWidth, gameHeight;
|
||
|
|
||
|
|
||
|
extern TextGL *largeTextFixed;
|
||
|
|
||
|
|
||
|
template <>
|
||
|
void SizeLimitedVector<GameState*>::deleteElementOfType(
|
||
|
GameState *inElement ) {
|
||
|
// special delete needed, because vector stores pointers
|
||
|
delete inElement;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
GameStateEditor::GameStateEditor( ScreenGL *inScreen )
|
||
|
: Editor( inScreen ),
|
||
|
mEditingSelectedObject( false ),
|
||
|
mUndoStack( MAX_UNDOS, true ), // stack contains pointers
|
||
|
mIgnoreObjPickerEvents( false ),
|
||
|
mObjectChanging( false ),
|
||
|
// gen a fake ID
|
||
|
mCurrentWorkingStateID( makeUniqueID( (unsigned char*)"currState",
|
||
|
strlen( "currState" ) ) ) {
|
||
|
|
||
|
AppLog::info( "Constructing game state editor\n" );
|
||
|
|
||
|
/*
|
||
|
LabelGL *titleLabel = new LabelGL( 0.75, 0.5, 0.25,
|
||
|
0.1, "Room Editor", largeText );
|
||
|
|
||
|
|
||
|
|
||
|
mSidePanel->add( titleLabel );
|
||
|
*/
|
||
|
|
||
|
// hide the close button for this editor, since it's the base editor
|
||
|
mCloseButton->setEnabled( false );
|
||
|
|
||
|
mSidePanel->add( mainStateObjectPicker );
|
||
|
|
||
|
mainStateObjectPicker->addActionListener( this );
|
||
|
|
||
|
|
||
|
mSidePanel->add( mainScenePicker );
|
||
|
|
||
|
mainScenePicker->addActionListener( this );
|
||
|
|
||
|
|
||
|
// listen for room changes too
|
||
|
mainRoomPicker->addActionListener( this );
|
||
|
|
||
|
|
||
|
|
||
|
mStateDisplay = new GameStateDisplay( 8, gameWidth - 48 - G * P,
|
||
|
true );
|
||
|
mMainPanel->add( mStateDisplay );
|
||
|
mStateDisplay->addActionListener( this );
|
||
|
|
||
|
// turn on active bubble coloring
|
||
|
mStateDisplay->mHighlightEditedBubble = true;
|
||
|
|
||
|
mStateDisplay->setEditor( this );
|
||
|
|
||
|
|
||
|
mainRoomEditor->setGameStateDisplay( mStateDisplay );
|
||
|
|
||
|
|
||
|
|
||
|
mEditStateObjectButton =
|
||
|
new EditButtonGL(
|
||
|
mainStateObjectPicker->getAnchorX() - 1,
|
||
|
mainStateObjectPicker->getAnchorY() +
|
||
|
mainStateObjectPicker->getHeight() + 1,
|
||
|
8,
|
||
|
8 );
|
||
|
|
||
|
mSidePanel->add( mEditStateObjectButton );
|
||
|
|
||
|
mEditStateObjectButton->addActionListener( this );
|
||
|
mEditStateObjectButton->setToolTip( "tip_edit_object" );
|
||
|
|
||
|
|
||
|
|
||
|
double offset = P;
|
||
|
|
||
|
double buttonSize = P;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mToolSet = new StateToolSet( 26, 42 );
|
||
|
mMainPanel->add( mToolSet );
|
||
|
mToolSet->addActionListener( this );
|
||
|
|
||
|
|
||
|
|
||
|
mSpeechDeleteButton = new QuickDeleteButtonGL(
|
||
|
mToolSet->getAnchorX() + mToolSet->getWidth(),
|
||
|
mToolSet->getAnchorY() + mToolSet->getHeight() - 8,
|
||
|
8,
|
||
|
8 );
|
||
|
mMainPanel->add( mSpeechDeleteButton );
|
||
|
mSpeechDeleteButton->addActionListener( this );
|
||
|
|
||
|
mSpeechDeleteButton->setEnabled( false );
|
||
|
|
||
|
mSpeechDeleteButton->setToolTip( "tip_delete_speech" );
|
||
|
|
||
|
|
||
|
|
||
|
mSpeechBubbleBoxButton = new ToggleSpriteButtonGL(
|
||
|
new Sprite( "speechBox.tga", true ),
|
||
|
new Sprite( "speechBubble.tga", true ),
|
||
|
1,
|
||
|
mToolSet->getAnchorX() + mToolSet->getWidth(),
|
||
|
mToolSet->getAnchorY(),
|
||
|
8,
|
||
|
8 );
|
||
|
mMainPanel->add( mSpeechBubbleBoxButton );
|
||
|
mSpeechBubbleBoxButton->addActionListener( this );
|
||
|
|
||
|
mSpeechBubbleBoxButton->setEnabled( false );
|
||
|
|
||
|
mSpeechBubbleBoxButton->setToolTip( "tip_toggle_box" );
|
||
|
mSpeechBubbleBoxButton->setSecondToolTip( "tip_toggle_bubble" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mFlipSpeechButton =
|
||
|
new FlipHButtonGL( mSpeechDeleteButton->getAnchorX()
|
||
|
+ mSpeechDeleteButton->getWidth() + 1,
|
||
|
44,
|
||
|
16, 16 );
|
||
|
mMainPanel->add( mFlipSpeechButton );
|
||
|
mFlipSpeechButton->addActionListener( this );
|
||
|
|
||
|
mFlipSpeechButton->setToolTip( "tip_flip_speech" );
|
||
|
mFlipSpeechButton->setEnabled( false );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
EightPixelLabel *fieldLabel = new EightPixelLabel( 150, 54,
|
||
|
"sceneName" );
|
||
|
mMainPanel->add( fieldLabel );
|
||
|
|
||
|
|
||
|
|
||
|
int fieldHeight = 8;
|
||
|
int fieldWidth = 8 * 10;
|
||
|
|
||
|
const char *defaultText = "default";
|
||
|
|
||
|
mNameField = new TextFieldGL( 150,
|
||
|
43,
|
||
|
fieldWidth,
|
||
|
fieldHeight,
|
||
|
1,
|
||
|
defaultText,
|
||
|
largeTextFixed,
|
||
|
new Color( 0.75, 0.75, 0.75 ),
|
||
|
new Color( 0.75, 0.75, 0.75 ),
|
||
|
new Color( 0.15, 0.15, 0.15 ),
|
||
|
new Color( 0.75, 0.75, 0.75 ),
|
||
|
10,
|
||
|
false );
|
||
|
mMainPanel->add( mNameField );
|
||
|
|
||
|
mNameField->setFocus( false );
|
||
|
//mNameField->lockFocus( true );
|
||
|
|
||
|
mNameField->setCursorPosition( strlen( defaultText ) );
|
||
|
|
||
|
// not undoable, ignore actions (so that we can hold
|
||
|
// focus on GameStateDisplay whenever we can)
|
||
|
//mNameField->addActionListener( this );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// center side buttons
|
||
|
double gridEdge = 8 + G * buttonSize;
|
||
|
|
||
|
double extra = gameHeight - gridEdge;
|
||
|
|
||
|
|
||
|
|
||
|
double sideButtonsX = gridEdge + (extra - 16) / 2;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
double undoButtonY = gameWidth - ( 48 + offset + (G - 1) * buttonSize );
|
||
|
|
||
|
mUndoButton = new UndoButtonGL( sideButtonsX, undoButtonY, 16, 16 );
|
||
|
mMainPanel->add( mUndoButton );
|
||
|
mUndoButton->addActionListener( this );
|
||
|
mUndoButton->setEnabled( false );
|
||
|
|
||
|
mRedoButton = new RedoButtonGL( sideButtonsX, undoButtonY + 19, 16, 16 );
|
||
|
mMainPanel->add( mRedoButton );
|
||
|
mRedoButton->addActionListener( this );
|
||
|
mRedoButton->setEnabled( false );
|
||
|
|
||
|
|
||
|
mUndoOrRedoOrClearAction = false;
|
||
|
mIgnoreSliders = false;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
double setY = mainStateObjectPicker->getAnchorY() +
|
||
|
mainStateObjectPicker->getHeight() - 15;
|
||
|
|
||
|
mSetObjectButton = new SpriteButtonGL(
|
||
|
new Sprite( "setObject.tga", true ),
|
||
|
1,
|
||
|
sideButtonsX, setY, 16, 16 );
|
||
|
|
||
|
mMainPanel->add( mSetObjectButton );
|
||
|
|
||
|
mSetObjectButton->addActionListener( this );
|
||
|
|
||
|
mSetObjectButton->setToolTip( "tip_objSet" );
|
||
|
|
||
|
|
||
|
|
||
|
mAddObjectButton = new KeyEquivButtonGL(
|
||
|
new Sprite( "addObject.tga", true ),
|
||
|
1,
|
||
|
sideButtonsX, setY - 20, 16, 16, 'a', 'A' );
|
||
|
|
||
|
mMainPanel->add( mAddObjectButton );
|
||
|
|
||
|
mAddObjectButton->addActionListener( this );
|
||
|
|
||
|
mAddObjectButton->setToolTip( "tip_objAdd" );
|
||
|
|
||
|
|
||
|
|
||
|
mEditObjectButton = new KeyEquivButtonGL(
|
||
|
new Sprite( "editObject.tga", true ),
|
||
|
1,
|
||
|
sideButtonsX, setY - 40, 16, 16, 'e', 'E' );
|
||
|
|
||
|
mMainPanel->add( mEditObjectButton );
|
||
|
|
||
|
mEditObjectButton->addActionListener( this );
|
||
|
|
||
|
mEditObjectButton->setToolTip( "tip_objEdit" );
|
||
|
|
||
|
|
||
|
mRemoveObjectButton = new KeyEquivButtonGL(
|
||
|
new Sprite( "removeObject.tga", true ),
|
||
|
1,
|
||
|
sideButtonsX, setY - 60, 16, 16, 'x', 'X' );
|
||
|
|
||
|
mMainPanel->add( mRemoveObjectButton );
|
||
|
|
||
|
mRemoveObjectButton->addActionListener( this );
|
||
|
|
||
|
mRemoveObjectButton->setToolTip( "tip_objRemove" );
|
||
|
|
||
|
// obj 0 starts out selected, can't be deleted
|
||
|
mRemoveObjectButton->setEnabled( false );
|
||
|
|
||
|
|
||
|
|
||
|
// freeze only works on obj 0, which can't be removed
|
||
|
// so re-use the space
|
||
|
// actually, reusing space causes cross-events on click--- UGH
|
||
|
// Also probably BAD UI design...
|
||
|
mFreezeButton = new SelectableButtonGL(
|
||
|
new Sprite( "freeze.tga", true ),
|
||
|
1,
|
||
|
104, 42, 20, 20 );
|
||
|
|
||
|
mMainPanel->add( mFreezeButton );
|
||
|
|
||
|
mFreezeButton->setSelected( false );
|
||
|
|
||
|
mFreezeButton->addActionListener( this );
|
||
|
|
||
|
mFreezeButton->setToolTip( "tip_freezePlayer" );
|
||
|
|
||
|
|
||
|
|
||
|
mLockSelectedButton = new SelectableButtonGL(
|
||
|
new Sprite( "lockSelected.tga", true ),
|
||
|
1,
|
||
|
104, 42, 20, 20 );
|
||
|
|
||
|
mMainPanel->add( mLockSelectedButton );
|
||
|
|
||
|
mLockSelectedButton->setSelected( false );
|
||
|
|
||
|
mLockSelectedButton->addActionListener( this );
|
||
|
|
||
|
mLockSelectedButton->setEnabled( false );
|
||
|
|
||
|
mLockSelectedButton->setToolTip( "tip_lockSelected" );
|
||
|
|
||
|
|
||
|
|
||
|
mLockGlobalButton = new SelectableButtonGL(
|
||
|
new Sprite( "lock.tga", true ),
|
||
|
1,
|
||
|
126, 42, 20, 20 );
|
||
|
|
||
|
mMainPanel->add( mLockGlobalButton );
|
||
|
|
||
|
mLockGlobalButton->setSelected( true );
|
||
|
|
||
|
mLockGlobalButton->addActionListener( this );
|
||
|
|
||
|
mLockGlobalButton->setEnabled( true );
|
||
|
|
||
|
mLockGlobalButton->setToolTip( "tip_lockGlobal" );
|
||
|
|
||
|
|
||
|
|
||
|
mHoldObjectButton = new SelectableButtonGL(
|
||
|
new Sprite( "hold.tga", true ),
|
||
|
1,
|
||
|
mLockSelectedButton->getAnchorX() - 13,
|
||
|
mLockSelectedButton->getAnchorY() + 2,
|
||
|
12, 12 );
|
||
|
|
||
|
|
||
|
mHoldObjectButton->setSelected( false );
|
||
|
|
||
|
mHoldObjectButton->setToolTip( "tip_holdObject" );
|
||
|
|
||
|
mMainPanel->add( mHoldObjectButton );
|
||
|
|
||
|
mHoldObjectButton->addActionListener( this );
|
||
|
|
||
|
|
||
|
|
||
|
Color *thumbColor = new Color( .5, .5, .5, .5 );
|
||
|
Color *borderColor = new Color( .35, .35, .35, .35 );
|
||
|
|
||
|
|
||
|
mObjectTransSlider = new ToolTipSliderGL( sideButtonsX - 1, setY - 80 + 9,
|
||
|
18, 10,
|
||
|
NULL, 0,
|
||
|
new Color( 0, 0, 0, 1 ),
|
||
|
new Color( 1, 1, 1, 1 ),
|
||
|
thumbColor->copy(),
|
||
|
borderColor->copy(),
|
||
|
1, 4, 1 );
|
||
|
|
||
|
mMainPanel->add( mObjectTransSlider );
|
||
|
mObjectTransSlider->setThumbPosition( 1.0 );
|
||
|
mObjectTransSlider->addActionListener( this );
|
||
|
mObjectTransSlider->setToolTip( "tip_object_fade" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mGridButton = new SelectableButtonGL(
|
||
|
new Sprite( "grid.tga", true ),
|
||
|
1,
|
||
|
sideButtonsX - 2, 158, 20, 20 );
|
||
|
|
||
|
mMainPanel->add( mGridButton );
|
||
|
|
||
|
mGridButton->setSelected( true );
|
||
|
|
||
|
mGridButton->addActionListener( this );
|
||
|
|
||
|
mGridButton->setToolTip( "tip_grid" );
|
||
|
|
||
|
|
||
|
|
||
|
mRoomTransSlider = new ToolTipSliderGL( sideButtonsX - 1, setY - 120 + 13,
|
||
|
18, 10,
|
||
|
NULL, 0,
|
||
|
new Color( 0, 0, 0, 1 ),
|
||
|
new Color( 1, 1, 1, 1 ),
|
||
|
thumbColor->copy(),
|
||
|
borderColor->copy(),
|
||
|
1, 4, 1 );
|
||
|
|
||
|
mMainPanel->add( mRoomTransSlider );
|
||
|
mRoomTransSlider->setThumbPosition( 1.0 );
|
||
|
mRoomTransSlider->addActionListener( this );
|
||
|
mRoomTransSlider->setToolTip( "tip_room_fade" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// center it vertically on scene picker
|
||
|
double addSceneY = mainScenePicker->getAnchorY() +
|
||
|
mainScenePicker->getHeight() - 15;
|
||
|
|
||
|
|
||
|
mAddSceneButton = new AddButtonGL( sideButtonsX,
|
||
|
addSceneY,
|
||
|
16, 16 );
|
||
|
mMainPanel->add( mAddSceneButton );
|
||
|
mAddSceneButton->addActionListener( this );
|
||
|
mAddSceneButton->setToolTip( "tip_addScene" );
|
||
|
|
||
|
mAddSceneAction = false;
|
||
|
|
||
|
double clearY = addSceneY - 20;
|
||
|
|
||
|
mClearButton = new ClearButtonGL( sideButtonsX, clearY, 16, 16 );
|
||
|
mMainPanel->add( mClearButton );
|
||
|
mClearButton->addActionListener( this );
|
||
|
|
||
|
|
||
|
|
||
|
mSendButton = new SendButtonGL(
|
||
|
4,
|
||
|
// below undo button
|
||
|
44,
|
||
|
16, 16 );
|
||
|
|
||
|
mMainPanel->add( mSendButton );
|
||
|
|
||
|
mSendButton->addActionListener( this );
|
||
|
|
||
|
mSendButton->setToolTip( "tip_send" );
|
||
|
|
||
|
|
||
|
|
||
|
mPracticeButton = new SpriteButtonGL(
|
||
|
new Sprite( "practice.tga", true ),
|
||
|
1,
|
||
|
4,
|
||
|
// below undo button
|
||
|
44,
|
||
|
16, 16 );
|
||
|
|
||
|
mMainPanel->add( mPracticeButton );
|
||
|
|
||
|
mPracticeButton->addActionListener( this );
|
||
|
|
||
|
mPracticeButton->setToolTip( "tip_practice" );
|
||
|
mPracticeButton->setEnabled( false );
|
||
|
|
||
|
|
||
|
// music button in side panel
|
||
|
double musicButtonY =
|
||
|
mainScenePicker->getAnchorY() + mainScenePicker->getHeight() +
|
||
|
(int)( mainStateObjectPicker->getAnchorY() -
|
||
|
( mainScenePicker->getAnchorY() + mainScenePicker->getHeight() )
|
||
|
- 16 ) / 2;
|
||
|
|
||
|
|
||
|
mEditMusicButton = new SpriteButtonGL(
|
||
|
new Sprite( "music.tga", true ),
|
||
|
1,
|
||
|
mSidePanel->getAnchorX() + ( mSidePanel->getWidth() - 16 ) / 2,
|
||
|
musicButtonY, 16, 16 );
|
||
|
|
||
|
mSidePanel->add( mEditMusicButton );
|
||
|
|
||
|
mEditMusicButton->addActionListener( this );
|
||
|
|
||
|
mEditMusicButton->setToolTip( "tip_edit_music" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mEditRoomButton = new SpriteButtonGL(
|
||
|
new Sprite( "editRoom.tga", true ),
|
||
|
1,
|
||
|
mainScenePicker->getAnchorX() - 1, musicButtonY, 16, 16 );
|
||
|
|
||
|
mSidePanel->add( mEditRoomButton );
|
||
|
|
||
|
mEditRoomButton->addActionListener( this );
|
||
|
|
||
|
mEditRoomButton->setToolTip( "tip_edit_room" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
delete thumbColor;
|
||
|
delete borderColor;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mEditStateObjectButton =
|
||
|
new EditButtonGL(
|
||
|
mainStateObjectPicker->getAnchorX() - 1,
|
||
|
mainStateObjectPicker->getAnchorY() +
|
||
|
mainStateObjectPicker->getHeight() + 1,
|
||
|
8,
|
||
|
8 );
|
||
|
|
||
|
mSidePanel->add( mEditStateObjectButton );
|
||
|
|
||
|
mEditStateObjectButton->addActionListener( this );
|
||
|
mEditStateObjectButton->setToolTip( "tip_edit_object" );
|
||
|
|
||
|
|
||
|
|
||
|
mAddToPackButton = new ToggleSpriteButtonGL(
|
||
|
new Sprite( "pack.tga", true ),
|
||
|
new Sprite( "packAlreadyIn.tga", true ),
|
||
|
1,
|
||
|
mainScenePicker->getAnchorX() + mainScenePicker->getWidth() - 22,
|
||
|
mainScenePicker->getAnchorY() +
|
||
|
mainScenePicker->getHeight() + 1,
|
||
|
8,
|
||
|
8 );
|
||
|
|
||
|
mSidePanel->add( mAddToPackButton );
|
||
|
|
||
|
mAddToPackButton->addActionListener( this );
|
||
|
|
||
|
mAddToPackButton->setToolTip( "tip_addSceneToPack" );
|
||
|
mAddToPackButton->setSecondToolTip( "tip_sceneAlreadyInPack" );
|
||
|
|
||
|
|
||
|
mSavePackButton = new SpriteButtonGL(
|
||
|
new Sprite( "packSave.tga", true ),
|
||
|
1,
|
||
|
mainScenePicker->getAnchorX() + mainScenePicker->getWidth() - 7,
|
||
|
mainScenePicker->getAnchorY() +
|
||
|
mainScenePicker->getHeight() + 1,
|
||
|
8,
|
||
|
8 );
|
||
|
|
||
|
mSidePanel->add( mSavePackButton );
|
||
|
|
||
|
mSavePackButton->addActionListener( this );
|
||
|
|
||
|
mSavePackButton->setToolTip( "tip_savePack" );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
mGameStateToEdit = NULL;
|
||
|
|
||
|
GameState *state = new GameState();
|
||
|
|
||
|
setGameStateToEdit( state );
|
||
|
|
||
|
|
||
|
|
||
|
mNoDropImage = readTGA( "noDrop.tga" );
|
||
|
mCanDropImage = readTGA( "canDrop.tga" );
|
||
|
|
||
|
|
||
|
|
||
|
// listen for clicks on main panel so we can re-focus for speech input
|
||
|
mMainPanel->addActionListener( this );
|
||
|
|
||
|
|
||
|
// dnd on top of side panel
|
||
|
postConstructionSide();
|
||
|
|
||
|
mMainPanel->add( mainDragAndDrop );
|
||
|
|
||
|
// but *below* special main panel widgets
|
||
|
postConstructionMain();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
GameStateEditor::~GameStateEditor() {
|
||
|
mSidePanel->remove( mainStateObjectPicker );
|
||
|
mSidePanel->remove( mainScenePicker );
|
||
|
|
||
|
mMainPanel->remove( mainDragAndDrop );
|
||
|
|
||
|
if( mGameStateToEdit != NULL ) {
|
||
|
delete mGameStateToEdit;
|
||
|
}
|
||
|
|
||
|
int numInStack = mUndoStack.size();
|
||
|
int i;
|
||
|
for( i=0; i<numInStack; i++ ) {
|
||
|
delete *( mUndoStack.getElement( i ) );
|
||
|
}
|
||
|
|
||
|
clearRedoStack();
|
||
|
|
||
|
delete mNoDropImage;
|
||
|
delete mCanDropImage;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::setGameStateToEdit( GameState *inGameState,
|
||
|
char inUpdatePickers ) {
|
||
|
|
||
|
AppLog::trace(
|
||
|
"Setting new game state, generating new display sprites\n" );
|
||
|
|
||
|
if( mGameStateToEdit != NULL ) {
|
||
|
delete mGameStateToEdit;
|
||
|
}
|
||
|
|
||
|
// clear old working usages
|
||
|
removeUsages( mCurrentWorkingStateID );
|
||
|
|
||
|
|
||
|
|
||
|
mGameStateToEdit = inGameState;
|
||
|
|
||
|
|
||
|
if( inUpdatePickers ) {
|
||
|
|
||
|
int selectedObj = mGameStateToEdit->getSelectedObject();
|
||
|
|
||
|
|
||
|
StateObjectInstance *inst =
|
||
|
*( mGameStateToEdit->
|
||
|
mObjects.getElement( selectedObj ) );
|
||
|
|
||
|
|
||
|
mainStateObjectPicker->setSelectedResource(
|
||
|
inst->mObject );
|
||
|
|
||
|
|
||
|
|
||
|
mainRoomPicker->setSelectedResource( mGameStateToEdit->mRoom );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
mStateDisplay->setState( mGameStateToEdit->copy() );
|
||
|
|
||
|
|
||
|
|
||
|
// make sure speech toggles match current state (in case of undo/redo)
|
||
|
mStateDisplay->mEditingSpeech =
|
||
|
( mToolSet->getSelected() == speak );
|
||
|
|
||
|
// always keep focus on display...
|
||
|
//mStateDisplay->setFocus( mStateDisplay->mEditingSpeech );
|
||
|
|
||
|
// show delete button whenever non-empty speech object selected,
|
||
|
// even if not currently in Speech mode
|
||
|
if( mGameStateToEdit->getSelectedSpeechLength() > 0 ) {
|
||
|
mSpeechDeleteButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
mSpeechDeleteButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
if( mGameStateToEdit->getSelectedObject() > 0 ) {
|
||
|
mRemoveObjectButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
// never delete object 0 (player object)
|
||
|
mRemoveObjectButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
mFreezeButton->setSelected( mGameStateToEdit->isObjectZeroFrozen() );
|
||
|
|
||
|
mFreezeButton->setEnabled( mGameStateToEdit->getSelectedObject() == 0 );
|
||
|
|
||
|
int selectedObjectIndex = mGameStateToEdit->getSelectedObject();
|
||
|
|
||
|
mLockSelectedButton->setEnabled( selectedObjectIndex != 0 );
|
||
|
|
||
|
mLockSelectedButton->setSelected(
|
||
|
mGameStateToEdit->getSelectedLocked() );
|
||
|
|
||
|
mLockGlobalButton->setSelected(
|
||
|
mGameStateToEdit->mLocksOn );
|
||
|
|
||
|
mHoldObjectButton->setSelected(
|
||
|
mGameStateToEdit->getObjectHeld( selectedObjectIndex ) );
|
||
|
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
|
||
|
if( mGameStateToEdit->getSelectedSpeechLength() > 0 ) {
|
||
|
mSpeechDeleteButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
mSpeechDeleteButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
mIgnoreSliders = true;
|
||
|
|
||
|
// only 36 pixels in slider... avoid round-off errors
|
||
|
mRoomTransSlider->setThumbPosition(
|
||
|
(int)( mGameStateToEdit->mRoomTrans / 255.0 * 36 ) / 36.0 );
|
||
|
|
||
|
mObjectTransSlider->setThumbPosition(
|
||
|
(int)( mGameStateToEdit->getSelectedTrans() / 255.0 * 36 ) / 36.0 );
|
||
|
|
||
|
mIgnoreSliders = false;
|
||
|
|
||
|
mAddObjectButton->setEnabled( mGameStateToEdit->canAdd() );
|
||
|
|
||
|
getTileUnder();
|
||
|
|
||
|
|
||
|
// add usages for current working state
|
||
|
int numObjects = mGameStateToEdit->mObjects.size();
|
||
|
for( int i=0; i<numObjects; i++ ) {
|
||
|
StateObjectInstance *obj =
|
||
|
*( mGameStateToEdit->mObjects.getElement( i ) );
|
||
|
addUsage( mCurrentWorkingStateID, obj->mObject.getUniqueID() );
|
||
|
}
|
||
|
mainStateObjectPicker->recheckDeletable();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#include "Connection.h"
|
||
|
|
||
|
|
||
|
extern Connection *connection;
|
||
|
|
||
|
extern char practiceMode;
|
||
|
|
||
|
|
||
|
void GameStateEditor::enableSend( char inEnabled ) {
|
||
|
mSendButton->setEnabled( inEnabled );
|
||
|
|
||
|
mPracticeButton->setEnabled( false );
|
||
|
|
||
|
if( !inEnabled ) {
|
||
|
// show practice button?
|
||
|
|
||
|
if( !practiceMode &&
|
||
|
( connection == NULL || ! connection->isConnected() ) ) {
|
||
|
|
||
|
mPracticeButton->setEnabled( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::aboutToSend() {
|
||
|
mSendButton->setEnabled( false );
|
||
|
//mSendButton->resetPressState();
|
||
|
|
||
|
// clear player's actions/speech
|
||
|
StateObjectInstance *objZero =
|
||
|
*( mGameStateToEdit->mObjects.getElement( 0 ) );
|
||
|
|
||
|
delete [] objZero->mSpokenMessage;
|
||
|
objZero->mSpokenMessage = stringDuplicate( "" );
|
||
|
|
||
|
objZero->mAction[0] = '\0';
|
||
|
|
||
|
// re-center action (now empty) on player
|
||
|
mGameStateToEdit->resetActionAnchor( 0 );
|
||
|
|
||
|
|
||
|
// no need to redo all sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::clearRedoStack() {
|
||
|
int numInStack = mRedoStack.size();
|
||
|
for( int i=0; i<numInStack; i++ ) {
|
||
|
delete *( mRedoStack.getElement( i ) );
|
||
|
}
|
||
|
|
||
|
mRedoStack.deleteAll();
|
||
|
mRedoButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
void GameStateEditor::saveUndoPoint() {
|
||
|
mUndoStack.push_back( mGameStateToEdit->copy() );
|
||
|
mUndoButton->setEnabled( true );
|
||
|
|
||
|
// new branch, old redo future impossible
|
||
|
clearRedoStack();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::checkFlipAndDeleteSpeechButtonEnabled() {
|
||
|
int speechLength = mGameStateToEdit->getSelectedSpeechLength();
|
||
|
|
||
|
// show delete button whenever there is speech, even if not
|
||
|
// in delete mode.
|
||
|
if( speechLength > 0 ) {
|
||
|
mSpeechDeleteButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
mSpeechDeleteButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
int selObject = mGameStateToEdit->getSelectedObject();
|
||
|
|
||
|
StateObjectInstance *o =
|
||
|
*( mGameStateToEdit->mObjects.getElement( selObject ) );
|
||
|
|
||
|
mSpeechBubbleBoxButton->setState( o->mSpeechBox );
|
||
|
|
||
|
|
||
|
if( mStateDisplay->mEditingSpeech || speechLength > 0 ) {
|
||
|
|
||
|
// speech visible, always allow to switch to a box
|
||
|
mSpeechBubbleBoxButton->setEnabled( true );
|
||
|
|
||
|
|
||
|
|
||
|
int bubbleWidth = 64;
|
||
|
|
||
|
intPair bubblePos = ::add( o->mSpeechOffset, o->mAnchorPosition );
|
||
|
|
||
|
char offTop = mStateDisplay->getSpeechOffTop( selObject );
|
||
|
|
||
|
if( ! o->mSpeechBox && offTop ) {
|
||
|
bubbleWidth += 10;
|
||
|
}
|
||
|
|
||
|
int autoOffsetIfFlipped =
|
||
|
mGameStateToEdit->getAutoOffsetOnFlip( selObject );
|
||
|
|
||
|
if( !o->mSpeechFlip &&
|
||
|
bubblePos.x + autoOffsetIfFlipped - bubbleWidth < 0 ) {
|
||
|
// would be off left edge if flipped
|
||
|
mFlipSpeechButton->setEnabled( false );
|
||
|
}
|
||
|
else if( o->mSpeechFlip &&
|
||
|
bubblePos.x + autoOffsetIfFlipped + bubbleWidth >
|
||
|
P * G ) {
|
||
|
// would be off right edge if flipped
|
||
|
mFlipSpeechButton->setEnabled( false );
|
||
|
}
|
||
|
else {
|
||
|
mFlipSpeechButton->setEnabled( true );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// else speech bubble not even visible
|
||
|
mFlipSpeechButton->setEnabled( false );
|
||
|
mSpeechBubbleBoxButton->setEnabled( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::displayRedrawed() {
|
||
|
|
||
|
// don't wait for action to detect an auto-flip
|
||
|
if( mStateDisplay->mHasAnySpeechBeenAutoFlipped ) {
|
||
|
// make sure we get speech pos/flip tweaks added for display purposes
|
||
|
mStateDisplay->copySpeechCoordinates( mGameStateToEdit );
|
||
|
|
||
|
// got it!
|
||
|
mStateDisplay->mHasAnySpeechBeenAutoFlipped = false;
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::setSelectedObject( int inIndex ) {
|
||
|
|
||
|
int objIndex = inIndex;
|
||
|
|
||
|
mGameStateToEdit->setSelectedObject( objIndex );
|
||
|
|
||
|
mIgnoreSliders = true;
|
||
|
|
||
|
mObjectTransSlider->setThumbPosition(
|
||
|
(int)( mGameStateToEdit->getSelectedTrans() /
|
||
|
255.0 * 36 )
|
||
|
/ 36.0 );
|
||
|
|
||
|
mIgnoreSliders = false;
|
||
|
|
||
|
|
||
|
// ignore change events that we cause
|
||
|
mIgnoreObjPickerEvents = true;
|
||
|
|
||
|
// no need to generate all new sprites---it's slow!
|
||
|
//setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
|
||
|
mFreezeButton->setEnabled( objIndex == 0 );
|
||
|
mLockSelectedButton->setEnabled( objIndex != 0 );
|
||
|
|
||
|
mLockSelectedButton->setSelected(
|
||
|
mGameStateToEdit->getSelectedLocked() );
|
||
|
|
||
|
mHoldObjectButton->setSelected(
|
||
|
mGameStateToEdit->getObjectHeld( objIndex ) );
|
||
|
|
||
|
|
||
|
// switch obj picker
|
||
|
StateObjectInstance *inst =
|
||
|
*( mGameStateToEdit->
|
||
|
mObjects.getElement( objIndex ) );
|
||
|
|
||
|
mainStateObjectPicker->setSelectedResource(
|
||
|
inst->mObject );
|
||
|
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
|
||
|
mIgnoreObjPickerEvents = false;
|
||
|
|
||
|
if( objIndex > 0 ) {
|
||
|
// deleteable
|
||
|
mRemoveObjectButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
mRemoveObjectButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
getTileUnder();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::getTileUnder() {
|
||
|
StateObjectInstance *o =
|
||
|
*( mGameStateToEdit->mObjects.getElement(
|
||
|
mGameStateToEdit->getSelectedObject() ) );
|
||
|
|
||
|
uniqueID hitTileID = mGameStateToEdit->mRoom.getTile(
|
||
|
o->mAnchorPosition.x / P,
|
||
|
G - o->mAnchorPosition.y / P - 1 );
|
||
|
|
||
|
Tile hitTile( hitTileID );
|
||
|
|
||
|
mainTilePicker->setBackgroundTile( hitTile );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::actionPerformed( GUIComponent *inTarget ) {
|
||
|
// superclass
|
||
|
Editor::actionPerformed( inTarget );
|
||
|
|
||
|
|
||
|
if( inTarget == mainStateObjectPicker ) {
|
||
|
if( mainStateObjectPicker->wasLastActionFromPress() &&
|
||
|
this->isVisible() ) {
|
||
|
|
||
|
StateObject resource =
|
||
|
mainStateObjectPicker->getDraggedResource();
|
||
|
|
||
|
int numSprites = resource.getNumLayers();
|
||
|
|
||
|
|
||
|
int numTotalSprites = numSprites + 1;
|
||
|
|
||
|
intPair *offsets = new intPair[ numTotalSprites ];
|
||
|
Sprite **sprites = new Sprite*[ numTotalSprites ];
|
||
|
float *trans = new float[ numTotalSprites ];
|
||
|
char *glows = new char[ numTotalSprites ];
|
||
|
|
||
|
for( int i=0; i<numSprites; i++ ) {
|
||
|
offsets[i] = resource.getLayerOffset( i );
|
||
|
trans[i] = resource.getLayerTrans( i ) / 255.0f;
|
||
|
glows[i] = resource.getLayerGlow( i );
|
||
|
SpriteResource r( resource.getLayerSprite( i ) );
|
||
|
sprites[i] = r.getSprite( false, true );
|
||
|
}
|
||
|
|
||
|
Sprite *topSprite;
|
||
|
if( !mGameStateToEdit->canAdd() ) {
|
||
|
// buster on top
|
||
|
topSprite = new Sprite( mNoDropImage, true );
|
||
|
ToolTipManager::setTip(
|
||
|
(char*)TranslationManager::translate( "tip_sceneFull" ) );
|
||
|
}
|
||
|
else {
|
||
|
// nothing on top
|
||
|
topSprite = new Sprite( mCanDropImage, true );
|
||
|
|
||
|
ToolTipManager::setTip(
|
||
|
(char*)TranslationManager::translate(
|
||
|
"tip_draggingObjectScene" ) );
|
||
|
}
|
||
|
ToolTipManager::freeze( true );
|
||
|
|
||
|
offsets[numSprites].x = 0;
|
||
|
offsets[numSprites].y = 0;
|
||
|
trans[numSprites] = 0.5f;
|
||
|
glows[numSprites] = false;
|
||
|
sprites[numSprites] = topSprite;
|
||
|
|
||
|
|
||
|
mainDragAndDrop->setSprites( numTotalSprites, sprites, offsets,
|
||
|
trans, glows, 1 );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
int numSprites = resource.getNumLayers();
|
||
|
intPair *offsets = new intPair[ numSprites ];
|
||
|
Sprite **sprites = new Sprite*[ numSprites ];
|
||
|
float *trans = new float[ numSprites ];
|
||
|
|
||
|
for( int i=0; i<numSprites; i++ ) {
|
||
|
offsets[i] = resource.getLayerOffset( i );
|
||
|
trans[i] = resource.getLayerTrans( i ) / 255.0f;
|
||
|
SpriteResource r( resource.getLayerSprite( i ) );
|
||
|
sprites[i] = r.getSprite( false, true );
|
||
|
}
|
||
|
|
||
|
mainDragAndDrop->setSprites( numSprites, sprites, offsets,
|
||
|
trans, 1 );
|
||
|
*/
|
||
|
}
|
||
|
else if( ! mIgnoreObjPickerEvents && ! mUndoOrRedoOrClearAction &&
|
||
|
! mainStateObjectPicker->wasLastActionFromPress() ) {
|
||
|
|
||
|
// new obj picked through user picker action,
|
||
|
// replace selected object
|
||
|
|
||
|
// changed: don't do anything here
|
||
|
// wait for SetObjectButton
|
||
|
|
||
|
// except if selected object is default... then replace it
|
||
|
|
||
|
StateObjectInstance *objInstance =
|
||
|
*( mGameStateToEdit->mObjects.getElement(
|
||
|
mGameStateToEdit->getSelectedObject() ) );
|
||
|
|
||
|
if( ( mEditingSelectedObject &&
|
||
|
mainStateObjectEditor->isVisible() )
|
||
|
||
|
||
|
equal( objInstance->mObject.getUniqueID(),
|
||
|
StateObject::sBlankObject->getUniqueID() ) ) {
|
||
|
|
||
|
// we're editing the selected one
|
||
|
// OR
|
||
|
// selected object is blank (so we obviously should change it)
|
||
|
|
||
|
|
||
|
|
||
|
// replace automatically with newly-picked object
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->changeSelectedObject(
|
||
|
mainStateObjectPicker->getSelectedResource() );
|
||
|
|
||
|
// generate new sprites
|
||
|
setGameStateToEdit(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( inTarget == mainRoomPicker ) {
|
||
|
// ignore if this room change was triggered by our Undo/Redo
|
||
|
if( !mUndoOrRedoOrClearAction &&
|
||
|
! mainRoomPicker->wasLastActionFromPress() ) {
|
||
|
|
||
|
// will change room
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->mRoom = mainRoomPicker->getSelectedResource();
|
||
|
|
||
|
mStateDisplay->setState( mGameStateToEdit->copy() );
|
||
|
|
||
|
getTileUnder();
|
||
|
// don't pass through this, because it changes picker again
|
||
|
// setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
}
|
||
|
}
|
||
|
else if( inTarget == mainScenePicker ) {
|
||
|
|
||
|
Scene scenePicked = mainScenePicker->getSelectedResource();
|
||
|
|
||
|
// ignore if this scene change was triggered by an add
|
||
|
if( !mAddSceneAction &&
|
||
|
! mainScenePicker->wasLastActionFromPress() ) {
|
||
|
|
||
|
// will change everything
|
||
|
saveUndoPoint();
|
||
|
|
||
|
// block picker changes from firing
|
||
|
mUndoOrRedoOrClearAction = true;
|
||
|
|
||
|
|
||
|
|
||
|
GameState *loaded = new GameState();
|
||
|
|
||
|
char *sceneName = scenePicked.getSceneName();
|
||
|
|
||
|
mNameField->setText( sceneName );
|
||
|
|
||
|
delete [] sceneName;
|
||
|
|
||
|
// keep global lock button state intact
|
||
|
loaded->mLocksOn = mGameStateToEdit->mLocksOn;
|
||
|
|
||
|
Room loadedRoom( scenePicked.mRoom );
|
||
|
|
||
|
loaded->mRoom = loadedRoom;
|
||
|
loaded->mRoomTrans = scenePicked.mRoomTrans;
|
||
|
|
||
|
loaded->mObjectZeroFrozen = scenePicked.mObjectZeroFrozen;
|
||
|
|
||
|
|
||
|
int numObj = scenePicked.mObjects.size();
|
||
|
|
||
|
for( int i=0; i<numObj; i++ ) {
|
||
|
StateObject obj( *( scenePicked.mObjects.getElement( i ) ) );
|
||
|
|
||
|
char held = false;
|
||
|
if( i == 0 &&
|
||
|
mGameStateToEdit->getObjectHeld( 0 ) ) {
|
||
|
|
||
|
// copy object 0 over, ignoring obj 0 in scene
|
||
|
|
||
|
obj = ( *( mGameStateToEdit->mObjects.getElement( 0 ) ) )->
|
||
|
mObject;
|
||
|
held = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
intPair pos =
|
||
|
*( scenePicked.mObjectOffsets.getElement( i ) );
|
||
|
|
||
|
if( i == 0 ) {
|
||
|
// 0 already there in empty state... replace it
|
||
|
loaded->changeSelectedObject( obj );
|
||
|
loaded->moveSelectedObject( pos.x / P, pos.y / P );
|
||
|
}
|
||
|
else {
|
||
|
// add new, it will be selected
|
||
|
loaded->newObject( pos.x / P, pos.y / P, obj );
|
||
|
}
|
||
|
|
||
|
intPair speechOffset =
|
||
|
*( scenePicked.mSpeechOffsets.getElement( i ) );
|
||
|
intPair speechPos = add( speechOffset, pos );
|
||
|
|
||
|
loaded->moveSelectedSpeechAnchor( speechPos.x, speechPos.y );
|
||
|
|
||
|
if( *( scenePicked.mSpeechFlipFlags.getElement( i ) ) ) {
|
||
|
loaded->flipSelectedSpeech();
|
||
|
}
|
||
|
|
||
|
loaded->setSelectedSpeechBox(
|
||
|
*( scenePicked.mSpeechBoxFlags.getElement( i ) ) );
|
||
|
|
||
|
loaded->setSelectedLocked(
|
||
|
*( scenePicked.mLockedFlags.getElement( i ) ) );
|
||
|
|
||
|
loaded->adjustSelectedTrans(
|
||
|
*( scenePicked.mObjectTrans.getElement( i ) ) );
|
||
|
|
||
|
if( held ) {
|
||
|
// leave held status on for held objects across
|
||
|
// scene changes
|
||
|
loaded->setObjectHeld( i, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// finally, any non-player objects held are added ON TOP of the
|
||
|
// scene (in addition to all scene objects
|
||
|
|
||
|
int numOldObjects = mGameStateToEdit->mObjects.size();
|
||
|
for( int i=1; i<numOldObjects; i++ ) {
|
||
|
StateObjectInstance *objInst =
|
||
|
*( mGameStateToEdit->mObjects.getElement( i ) );
|
||
|
|
||
|
if( objInst->mHeld ) {
|
||
|
loaded->mObjects.push_back( objInst->copy() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// always switch to player object after loading a scene
|
||
|
loaded->setSelectedObject( 0 );
|
||
|
|
||
|
setGameStateToEdit( loaded );
|
||
|
|
||
|
mainStateObjectPicker->recheckDeletable();
|
||
|
|
||
|
mUndoOrRedoOrClearAction = false;
|
||
|
}
|
||
|
|
||
|
mAddToPackButton->setState(
|
||
|
alreadyInPack( scenePicked.getUniqueID() ) );
|
||
|
}
|
||
|
else if( inTarget == mAddSceneButton ) {
|
||
|
mAddSceneAction = true;
|
||
|
|
||
|
Scene sceneToSave;
|
||
|
|
||
|
sceneToSave.editSceneName( mNameField->getText() );
|
||
|
|
||
|
// pack game state into this scene
|
||
|
sceneToSave.mRoom = mGameStateToEdit->mRoom.getUniqueID();
|
||
|
|
||
|
sceneToSave.mRoomTrans = mGameStateToEdit->mRoomTrans;
|
||
|
|
||
|
sceneToSave.mObjectZeroFrozen =
|
||
|
mGameStateToEdit->mObjectZeroFrozen;
|
||
|
|
||
|
int numObj = mGameStateToEdit->mObjects.size();
|
||
|
|
||
|
for( int i=0; i<numObj; i++ ) {
|
||
|
StateObjectInstance *objInstance =
|
||
|
*( mGameStateToEdit->mObjects.getElement( i ) );
|
||
|
|
||
|
sceneToSave.mObjects.push_back(
|
||
|
objInstance->mObject.getUniqueID() );
|
||
|
|
||
|
sceneToSave.mObjectOffsets.push_back(
|
||
|
objInstance->mAnchorPosition );
|
||
|
|
||
|
sceneToSave.mSpeechOffsets.push_back(
|
||
|
objInstance->mSpeechOffset );
|
||
|
|
||
|
sceneToSave.mSpeechFlipFlags.push_back(
|
||
|
objInstance->mSpeechFlip );
|
||
|
|
||
|
sceneToSave.mSpeechBoxFlags.push_back(
|
||
|
objInstance->mSpeechBox );
|
||
|
|
||
|
sceneToSave.mLockedFlags.push_back(
|
||
|
objInstance->mLocked );
|
||
|
|
||
|
sceneToSave.mObjectTrans.push_back(
|
||
|
objInstance->mObjectTrans );
|
||
|
}
|
||
|
|
||
|
|
||
|
sceneToSave.finishEdit();
|
||
|
mainScenePicker->setSelectedResource( sceneToSave, true );
|
||
|
mainStateObjectPicker->recheckDeletable();
|
||
|
|
||
|
mAddSceneAction = false;
|
||
|
}
|
||
|
else if( inTarget == mSetObjectButton ) {
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->changeSelectedObject(
|
||
|
mainStateObjectPicker->getSelectedResource() );
|
||
|
|
||
|
// generate new sprites
|
||
|
setGameStateToEdit(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mAddObjectButton ) {
|
||
|
saveUndoPoint();
|
||
|
|
||
|
StateObject resource =
|
||
|
mainStateObjectPicker->getDraggedResource();
|
||
|
|
||
|
if( mStateDisplay->mMouseHover ) {
|
||
|
// mouse over grid
|
||
|
// add new object at mouse
|
||
|
mGameStateToEdit->newObject(
|
||
|
mStateDisplay->mLastHoverGridX,
|
||
|
mStateDisplay->mLastHoverGridY,
|
||
|
resource );
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
// center
|
||
|
mGameStateToEdit->newObject(
|
||
|
G / 2,
|
||
|
G / 2,
|
||
|
resource );
|
||
|
}
|
||
|
|
||
|
// generate new sprites
|
||
|
setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mEditObjectButton ) {
|
||
|
// editing selected... auto-replace
|
||
|
mEditingSelectedObject = true;
|
||
|
|
||
|
// make sure selected one is chosen in picker
|
||
|
mIgnoreObjPickerEvents = true;
|
||
|
|
||
|
StateObjectInstance *inst =
|
||
|
*( mGameStateToEdit->
|
||
|
mObjects.getElement(
|
||
|
mGameStateToEdit->getSelectedObject() ) );
|
||
|
|
||
|
mainStateObjectPicker->setSelectedResource(
|
||
|
inst->mObject );
|
||
|
mIgnoreObjPickerEvents = false;
|
||
|
|
||
|
showStateObjectEditor();
|
||
|
}
|
||
|
else if( inTarget == mRemoveObjectButton ) {
|
||
|
saveUndoPoint();
|
||
|
mGameStateToEdit->deleteSelectedObject();
|
||
|
|
||
|
if( mGameStateToEdit->getSelectedObject() > 0 ) {
|
||
|
mRemoveObjectButton->setEnabled( true );
|
||
|
}
|
||
|
else {
|
||
|
// never delete object 0 (player object)
|
||
|
mRemoveObjectButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mSendButton ) {
|
||
|
mSendButton->setEnabled( false );
|
||
|
|
||
|
fireActionPerformed( this );
|
||
|
}
|
||
|
else if( inTarget == mPracticeButton ) {
|
||
|
mPracticeButton->setEnabled( false );
|
||
|
practiceMode = true;
|
||
|
enableSend( true );
|
||
|
}
|
||
|
else if( inTarget == mEditStateObjectButton ) {
|
||
|
// edit whatever is in picker
|
||
|
mEditingSelectedObject = false;
|
||
|
showStateObjectEditor();
|
||
|
}
|
||
|
else if( inTarget == mEditRoomButton ) {
|
||
|
mStateDisplay->setHintMode( true );
|
||
|
mainRoomEditor->takeOverGameStateDisplay();
|
||
|
showRoomEditor();
|
||
|
}
|
||
|
else if( inTarget == mEditMusicButton ) {
|
||
|
showSongEditor();
|
||
|
}
|
||
|
else if( inTarget == mAddToPackButton ) {
|
||
|
Scene sceneToLoad = mainScenePicker->getSelectedResource();
|
||
|
|
||
|
AppLog::info( "Adding a scene to the current resource pack" );
|
||
|
sceneToLoad.saveToPack();
|
||
|
|
||
|
mAddToPackButton->setState( true );
|
||
|
}
|
||
|
else if( inTarget == mSavePackButton ) {
|
||
|
AppLog::info( "Saving the current resource pack" );
|
||
|
savePack();
|
||
|
|
||
|
mAddToPackButton->setState( false );
|
||
|
}
|
||
|
else if( inTarget == mUndoButton ) {
|
||
|
mUndoOrRedoOrClearAction = true;
|
||
|
|
||
|
int lastIndex = mUndoStack.size() - 1;
|
||
|
|
||
|
GameState *last = *( mUndoStack.getElement( lastIndex ) );
|
||
|
mUndoStack.deleteElement( lastIndex );
|
||
|
if( mUndoStack.size() == 0 ) {
|
||
|
mUndoButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
mRedoStack.push_back( mGameStateToEdit->copy() );
|
||
|
mRedoButton->setEnabled( true );
|
||
|
|
||
|
setGameStateToEdit( last );
|
||
|
|
||
|
mUndoOrRedoOrClearAction = false;
|
||
|
}
|
||
|
else if( inTarget == mRedoButton ) {
|
||
|
mUndoOrRedoOrClearAction = true;
|
||
|
|
||
|
int nextIndex = mRedoStack.size() - 1;
|
||
|
|
||
|
GameState *next = *( mRedoStack.getElement( nextIndex ) );
|
||
|
mRedoStack.deleteElement( nextIndex );
|
||
|
if( mRedoStack.size() == 0 ) {
|
||
|
mRedoButton->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
mUndoStack.push_back( mGameStateToEdit->copy() );
|
||
|
mUndoButton->setEnabled( true );
|
||
|
|
||
|
setGameStateToEdit( next );
|
||
|
|
||
|
mUndoOrRedoOrClearAction = false;
|
||
|
}
|
||
|
else if( inTarget == mToolSet ) {
|
||
|
// tool change?
|
||
|
|
||
|
// we only care about one:
|
||
|
// if speech tool, switch keyboard to main display
|
||
|
|
||
|
mStateDisplay->mEditingSpeech =
|
||
|
( mToolSet->getSelected() == speak );
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
}
|
||
|
else if( inTarget == mSpeechDeleteButton ) {
|
||
|
saveUndoPoint();
|
||
|
mGameStateToEdit->deleteAllCharsFromSelectedSpeech();
|
||
|
|
||
|
if( mGameStateToEdit->getSelectedObject() == 0 ) {
|
||
|
|
||
|
// clear player's action too
|
||
|
StateObjectInstance *objZero =
|
||
|
*( mGameStateToEdit->mObjects.getElement( 0 ) );
|
||
|
|
||
|
|
||
|
objZero->mAction[0] = '\0';
|
||
|
|
||
|
// re-center action (now empty) on player
|
||
|
mGameStateToEdit->resetActionAnchor( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
// no need to redo all sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
}
|
||
|
else if( inTarget == mFlipSpeechButton ) {
|
||
|
saveUndoPoint();
|
||
|
|
||
|
int selObject = mGameStateToEdit->getSelectedObject();
|
||
|
|
||
|
StateObjectInstance *o =
|
||
|
*( mGameStateToEdit->mObjects.getElement( selObject ) );
|
||
|
|
||
|
o->mSpeechOffset.x +=
|
||
|
mGameStateToEdit->getAutoOffsetOnFlip( selObject );
|
||
|
|
||
|
mGameStateToEdit->flipSelectedSpeech();
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mSpeechBubbleBoxButton ) {
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->setSelectedSpeechBox(
|
||
|
mSpeechBubbleBoxButton->getState() );
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mGridButton ) {
|
||
|
// toggle
|
||
|
mGridButton->setSelected( ! mGridButton->getSelected() );
|
||
|
|
||
|
mStateDisplay->showGrid( mGridButton->getSelected() );
|
||
|
}
|
||
|
else if( inTarget == mFreezeButton ) {
|
||
|
// toggle
|
||
|
mFreezeButton->setSelected( ! mFreezeButton->getSelected() );
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->freezeObjectZero( mFreezeButton->getSelected() );
|
||
|
|
||
|
// don't need to update display at all
|
||
|
}
|
||
|
else if( inTarget == mLockSelectedButton ) {
|
||
|
// toggle
|
||
|
mLockSelectedButton->setSelected(
|
||
|
! mLockSelectedButton->getSelected() );
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
|
||
|
mGameStateToEdit->setSelectedLocked(
|
||
|
mLockSelectedButton->getSelected() );
|
||
|
|
||
|
if( mGameStateToEdit->mLocksOn ) {
|
||
|
// look for an unlocked object to make selected
|
||
|
char objChange = false;
|
||
|
|
||
|
while( mGameStateToEdit->getSelectedLocked() ) {
|
||
|
mGameStateToEdit->setSelectedObject(
|
||
|
mGameStateToEdit->getSelectedObject() - 1 );
|
||
|
objChange = true;
|
||
|
}
|
||
|
if( objChange ) {
|
||
|
setSelectedObject( mGameStateToEdit->getSelectedObject() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mLockGlobalButton ) {
|
||
|
mLockGlobalButton->setSelected( ! mLockGlobalButton->getSelected() );
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->mLocksOn = mLockGlobalButton->getSelected();
|
||
|
|
||
|
if( mGameStateToEdit->mLocksOn ) {
|
||
|
// look for an unlocked object to make selected
|
||
|
char objChange = false;
|
||
|
|
||
|
while( mGameStateToEdit->getSelectedLocked() ) {
|
||
|
mGameStateToEdit->setSelectedObject(
|
||
|
mGameStateToEdit->getSelectedObject() - 1 );
|
||
|
objChange = true;
|
||
|
}
|
||
|
if( objChange ) {
|
||
|
setSelectedObject( mGameStateToEdit->getSelectedObject() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mHoldObjectButton ) {
|
||
|
// toggle
|
||
|
mHoldObjectButton->setSelected(
|
||
|
! mHoldObjectButton->getSelected() );
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
|
||
|
mGameStateToEdit->setObjectHeld(
|
||
|
mGameStateToEdit->getSelectedObject(),
|
||
|
mHoldObjectButton->getSelected() );
|
||
|
|
||
|
// don't update anything display-wise
|
||
|
}
|
||
|
else if( inTarget == mRoomTransSlider && ! mIgnoreSliders ) {
|
||
|
if( mRoomTransSlider->mJustPressed ) {
|
||
|
// first move in this adjustment, save an undo point here
|
||
|
saveUndoPoint();
|
||
|
}
|
||
|
|
||
|
mGameStateToEdit->mRoomTrans =
|
||
|
(unsigned char)( 255 * mRoomTransSlider->getThumbPosition() );
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mObjectTransSlider && ! mIgnoreSliders ) {
|
||
|
if( mObjectTransSlider->mJustPressed ) {
|
||
|
// first move in this adjustment, save an undo point here
|
||
|
saveUndoPoint();
|
||
|
}
|
||
|
|
||
|
mGameStateToEdit->adjustSelectedTrans(
|
||
|
(unsigned char)( 255 * mObjectTransSlider->getThumbPosition() ) );
|
||
|
|
||
|
// don't redo sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( inTarget == mClearButton ) {
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->mRoom = Room::getDefaultResource();
|
||
|
|
||
|
mGameStateToEdit->mRoomTrans = 255;
|
||
|
|
||
|
|
||
|
mGameStateToEdit->deleteSelectedObject();
|
||
|
|
||
|
int numObjects = mGameStateToEdit->mObjects.size();
|
||
|
|
||
|
// don't delete obj 0
|
||
|
for( int i=numObjects-1; i>0; i-- ) {
|
||
|
mGameStateToEdit->setSelectedObject( i );
|
||
|
mGameStateToEdit->deleteSelectedObject();
|
||
|
}
|
||
|
// obj 0 left and selected
|
||
|
mGameStateToEdit->changeSelectedObject(
|
||
|
StateObject::getDefaultResource() );
|
||
|
|
||
|
mGameStateToEdit->deleteAllCharsFromSelectedSpeech();
|
||
|
|
||
|
// revert
|
||
|
mGameStateToEdit->adjustSelectedTrans( 255 );
|
||
|
|
||
|
|
||
|
// leave action in place (controller cannot edit it)
|
||
|
|
||
|
|
||
|
// mStateDisplay->setState( mGameStateToEdit->copy() );
|
||
|
mUndoOrRedoOrClearAction = true;
|
||
|
|
||
|
setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
|
||
|
mUndoOrRedoOrClearAction = false;
|
||
|
}
|
||
|
else if( inTarget == mStateDisplay
|
||
|
&&
|
||
|
!mRoomTransSlider->mDragging
|
||
|
&&
|
||
|
!mObjectTransSlider->mDragging ) {
|
||
|
// ignore display events if dragging off edge of slider
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
if( mStateDisplay->mLastActionRelease ) {
|
||
|
// grab hit room tile and set it as bg tile for other pickers
|
||
|
uniqueID hitTileID = mGameStateToEdit->mRoom.getTile(
|
||
|
mStateDisplay->mLastGridClickX,
|
||
|
G - mStateDisplay->mLastGridClickY - 1 );
|
||
|
|
||
|
Tile hitTile( hitTileID );
|
||
|
|
||
|
mainTilePicker->setBackgroundTile( hitTile );
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
if( mStateDisplay->mLastActionRelease &&
|
||
|
mainDragAndDrop->isDragging() ) {
|
||
|
|
||
|
// add new obj
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
if( mGameStateToEdit->canAdd() ) {
|
||
|
|
||
|
StateObject resource =
|
||
|
mainStateObjectPicker->getDraggedResource();
|
||
|
|
||
|
|
||
|
mGameStateToEdit->newObject(
|
||
|
mStateDisplay->mLastGridClickX,
|
||
|
mStateDisplay->mLastGridClickY,
|
||
|
resource );
|
||
|
}
|
||
|
|
||
|
setGameStateToEdit( mGameStateToEdit->copy() );
|
||
|
}
|
||
|
else if( !mainDragAndDrop->isDragging() ) {
|
||
|
|
||
|
|
||
|
|
||
|
if( mToolSet->getSelected() == move ) {
|
||
|
// pick object anchor whenever we press over it with move tool
|
||
|
// tool it is
|
||
|
if( mStateDisplay->mLastActionPress ) {
|
||
|
|
||
|
int objIndex = mGameStateToEdit->getHitObject(
|
||
|
mStateDisplay->mLastGridClickX,
|
||
|
mStateDisplay->mLastGridClickY );
|
||
|
|
||
|
if( objIndex != -1 ) {
|
||
|
int oldSelected =
|
||
|
mGameStateToEdit->getSelectedObject();
|
||
|
|
||
|
if( oldSelected != objIndex ) {
|
||
|
mObjectChanging = true;
|
||
|
|
||
|
saveUndoPoint();
|
||
|
|
||
|
setSelectedObject( objIndex );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// allow typing whenever, even if not in speech mode
|
||
|
// but never let Controller type into Player's bubble
|
||
|
if( mStateDisplay->mLastActionKeyPress &&
|
||
|
mGameStateToEdit->getSelectedObject() != 0 ) {
|
||
|
unsigned char key = mStateDisplay->mLastKeyPressed;
|
||
|
|
||
|
if( key == 127 || key == 8 ) {
|
||
|
// backspace and delete
|
||
|
saveUndoPoint();
|
||
|
|
||
|
mGameStateToEdit->deleteCharFromSelectedSpeech();
|
||
|
}
|
||
|
else if( (key >= 32 && key <= 126)
|
||
|
|| key >= 160 ) {
|
||
|
// allowed range, ascii and extended ascii
|
||
|
|
||
|
// only save undo points before a space is pressed
|
||
|
// or before first chars are typed
|
||
|
if( key == 32 ||
|
||
|
mGameStateToEdit->getSelectedSpeechLength() ==
|
||
|
0 ) {
|
||
|
|
||
|
saveUndoPoint();
|
||
|
}
|
||
|
|
||
|
mGameStateToEdit->addCharToSelectedSpeech(
|
||
|
(char)key );
|
||
|
}
|
||
|
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
|
||
|
|
||
|
// no need to redo all sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
switch( mToolSet->getSelected() ) {
|
||
|
case move: {
|
||
|
if( !mStateDisplay->mLastActionKeyPress ) {
|
||
|
|
||
|
// only save an undo point when mouse initially pressed
|
||
|
// (ignore micro-state changes until release)
|
||
|
// undo point already saved if object changing
|
||
|
if( !mObjectChanging &&
|
||
|
mStateDisplay->mLastActionPress ) {
|
||
|
saveUndoPoint();
|
||
|
}
|
||
|
|
||
|
// move even in response to mouse dragging
|
||
|
|
||
|
// whole object only
|
||
|
mGameStateToEdit->moveSelectedObject(
|
||
|
mStateDisplay->mLastGridClickX,
|
||
|
mStateDisplay->mLastGridClickY );
|
||
|
|
||
|
// no need to generate all new sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
|
||
|
// flip might become forbidden because of move
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
|
||
|
getTileUnder();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case speak: {
|
||
|
if( !mStateDisplay->mLastActionKeyPress ) {
|
||
|
// mouse movement with speech tool
|
||
|
// adjust speech anchor
|
||
|
|
||
|
// ignore this if this mouse action is picking
|
||
|
// a new object
|
||
|
if( !mObjectChanging ) {
|
||
|
|
||
|
// only save an undo point when mouse
|
||
|
// initially pressed
|
||
|
// (ignore micro-state changes until release)
|
||
|
if( mStateDisplay->mLastActionPress ) {
|
||
|
saveUndoPoint();
|
||
|
}
|
||
|
|
||
|
|
||
|
mGameStateToEdit->moveSelectedSpeechAnchor(
|
||
|
mStateDisplay->mLastPixelClickX,
|
||
|
mStateDisplay->mLastPixelClickY );
|
||
|
|
||
|
|
||
|
// no need to generate all new sprites
|
||
|
mStateDisplay->updateSpritePositions(
|
||
|
mGameStateToEdit->copy() );
|
||
|
mStateDisplay->mManualBubblePositioningLive = true;
|
||
|
|
||
|
// flip might become forbidden because of move
|
||
|
checkFlipAndDeleteSpeechButtonEnabled();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// if mouse released, object change is over
|
||
|
if( mStateDisplay->mLastActionRelease ) {
|
||
|
mObjectChanging = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if( ! mNameField->isFocused() &&
|
||
|
! mainStateObjectPicker->isSearchFieldFocused() &&
|
||
|
! mainScenePicker->isSearchFieldFocused() ) {
|
||
|
|
||
|
|
||
|
// always refocus whenever an action happens
|
||
|
// essentially, keep focus on display always
|
||
|
// (except when user edits Scene name or types in a search box)
|
||
|
mStateDisplay->setFocus( true );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void GameStateEditor::editorClosing() {
|
||
|
}
|