Source

rwkc / src / editor.d

Full commit

module editor;

import derelict.sdl.sdl;
import view;
import gamepart;
import inputmanager;
import gameconstants;
import texturemanager;
import screen;
import editortools;
import gui;
import editoractions;
import map;
import editordialogs;

debug import std.stdio;

class Editor: public GamePart {

	GAMEPART_STATE mState;
	SDL_Surface* mBg;

	EditorTools mTools;
	ActionType mAction;
	string mPointerIcon;
	char mTileCode;
	bool mFromGame;
	SDL_Rect mHighlightRect;
	SDL_Surface* mHighlight;
	MapNameDialog mMapNameDialog;
	MapListDialog mMapListDialog;
	ParamsDialog mParamsDialog;
	string mPreviousPointer;
	Alert mAlert;

	int mMouseX, mMouseY;

	void delegate() fMode;
	void delegate() fPreviousMode;

	this( bool fromGame=false ) {

		// if coming from game ( test mode ), reload the map
		// else load an empty map.
		mFromGame = fromGame;
		string map_name;
		if( gMap !is null ) {
			 map_name = gMap.name;
			delete gMap;
		}
		if( fromGame && map_name.length>0 ) new Map( map_name );
		else new Map("");

		gView.setTarget( null );

		mBg = gTextureManager.get( "background.png" );

		mAction = ActionType.NOTHING;

		fMode = &editMode;
	}

	~this() {
		if( mTools !is null ) delete( mTools );
		if( mHighlight != null ) SDL_FreeSurface( mHighlight );
	}

	void update() {
		SDL_BlitSurface( mBg, null, gScreen.mSurface, null );

		gView.update();
		gView.draw();
		fMode();
	}

	void editMode() {
		GUI.instance.update();

		checkEscapeToQuit();

		if( gInputManager.isMouseButtonUp(SDL_BUTTON_MIDDLE) ) {
			mTools = new EditorTools;
			GUI.instance.changePointer( "pointer.png" );
			fMode = &toolsMode;
			return;
		}

		if ( gInputManager.isMouseButtonDown(SDL_BUTTON_RIGHT) ) {
			GUI.instance.hidePointer();
			fPreviousMode = &editMode;
			fMode = &moveMode;

			gInputManager.getMousePosition( mMouseX, mMouseY );
			SDL_WarpMouse( gScreen.WIDTH/2, gScreen.HEIGHT/2 );
			return;
		}

		// highligtht action
		int x,y;
		GUI.instance.getPointerPosition( x, y );
		int xOffset = cast(int)gView.mX / gMap.TILE_WIDTH;
		int yOffset = cast(int)gView.mY / gMap.TILE_HEIGHT;
		int xMap = x / gMap.TILE_WIDTH;
		int yMap = y / gMap.TILE_HEIGHT;
		int xHL = xMap * gMap.TILE_WIDTH - (cast(int)gView.mX % gMap.TILE_WIDTH);
		int yHL = yMap * gMap.TILE_HEIGHT - (cast(int)gView.mY % gMap.TILE_HEIGHT);


		switch( mAction ) {
			case ActionType.DELETE_COLUMN:
			case ActionType.INSERT_COLUMN:
				highlight( xHL, 0, gMap.TILE_WIDTH, 480 );
			break;

			case ActionType.DELETE_LINE:
			case ActionType.INSERT_LINE:
				highlight( 0, yHL, 640, gMap.TILE_HEIGHT );
			break;

			case ActionType.DELETE_TILE:
			case ActionType.ADD_TILE:
				highlight( xHL, yHL, gMap.TILE_WIDTH, gMap.TILE_HEIGHT );
			break;

			default:
			break;
		}

		// do action if click
		bool action;
		if( mAction == ActionType.ADD_TILE || mAction == ActionType.DELETE_TILE ) {
			action=gInputManager.isMouseButtonPressed(SDL_BUTTON_LEFT);
		}
		else {
			action=gInputManager.isMouseButtonUp(SDL_BUTTON_LEFT);
		}
		if( action ) {
			switch( mAction ) {
				case ActionType.INSERT_COLUMN:
					gMap.insertColumn( xMap + xOffset );
				break;

				case ActionType.DELETE_COLUMN:
					gMap.deleteColumn( xMap + xOffset );
				break;

				case ActionType.INSERT_LINE:
					gMap.insertRow( yMap + yOffset );
				break;

				case ActionType.DELETE_LINE:
					gMap.deleteRow( yMap + yOffset );
				break;

				case ActionType.ADD_TILE:
					gMap.replaceTile( xMap+xOffset, yMap+yOffset, mTileCode );
					gView.setTarget( null ); // to reset the target set in Hero.
				break;

				case ActionType.DELETE_TILE:
					gMap.removeTile( xMap+xOffset, yMap+yOffset );
				break;

				default:
				break;
			}
		}
	}

	void moveMode() {

		if ( gInputManager.isMouseButtonUp(SDL_BUTTON_RIGHT) ) {
			SDL_WarpMouse( cast(ushort)mMouseX, cast(ushort)mMouseY );
			GUI.instance.showPointer();
			fMode = fPreviousMode;
		}
		else {

			// movement relative to the center of the screen
			// manually computed because of the SDL relative events generated by
			// WarpMouse...
			gView.moveRelative(
				(gInputManager.mouseX-gScreen.WIDTH/2),
				(gInputManager.mouseY-gScreen.HEIGHT/2) );

			SDL_WarpMouse( gScreen.WIDTH/2, gScreen.HEIGHT/2 );
		}

	}


	void toolsMode() {
		int x,y;
		gInputManager.getMousePositionRelative( x,y );

		if ( gInputManager.isMouseButtonPressed(SDL_BUTTON_RIGHT) ) {
			GUI.instance.hidePointer();
			fPreviousMode = &toolsMode;
			fMode = &moveMode;
			return;
		}

		GUI.instance.update();

		if( gInputManager.isMouseButtonUp(SDL_BUTTON_MIDDLE) ) {
			delete(mTools);
			fMode = &editMode;
			if( mPointerIcon.length > 0 ) GUI.instance.changePointer( mPointerIcon );
			return;
		}

		if( mTools.done() ) {
			mAction = mTools.getAction();

			switch( mAction ) {
				case ActionType.LOAD_MAP:
					mMapListDialog = new MapListDialog();
					fMode=&mapLoadMode;
				break;

				case ActionType.SAVE_MAP:
					if( gMap.name != "" ) {
						saveMap();
					}
					else {
						mMapNameDialog = new MapNameDialog("");
						fMode=&saveAsMode;
					}
				break;

				case ActionType.TEST_MAP:
					//mAlert = new Alert("Not implemented yet !");
					//fMode=&mapTestMode;
					mState = GAMEPART_STATE.CONTINUE;
					//fMode = &alertMode;
					//fPreviousMode = &editMode;
				break;

				case ActionType.QUIT_EDITOR:
					quit();
				break;

				case ActionType.PARAMS:
					mParamsDialog = new ParamsDialog(gMap.mName, gMap.mAuthor, gMap.mParTime );
					fMode = &paramsMode;
				break;

				case ActionType.SAVE_AS:
					mMapNameDialog = new MapNameDialog(gMap.name);
					fMode=&saveAsMode;
				break;

				case ActionType.INSERT_COLUMN:
				case ActionType.DELETE_COLUMN:
				case ActionType.INSERT_LINE:
				case ActionType.DELETE_LINE:
				case ActionType.ADD_TILE:
				case ActionType.DELETE_TILE:
					mPointerIcon = mTools.getBitmap();
					GUI.instance.changePointer( mPointerIcon );
					mTileCode = mTools.getCode();
					fMode = &editMode;
				break;

				default:
				break;
			}

			delete( mTools );
		}
	}


	void checkEscapeToQuit() {
		if( gInputManager.isReleased( IMA_BACK )) {	quit();	}
	}

	void quit() {
		/*if( mFromGame)
			mState = GAMEPART_STATE.CONTINUE;
		else */
			mState = GAMEPART_STATE.MAIN_MENU;
	}

	void saveAsMode() {

		GUI.instance.update();

		if( mMapNameDialog.done() ) {
			if( mMapNameDialog.ok && mMapNameDialog.text != "" ) {
				gMap.name= std.string.strip(mMapNameDialog.text);
				saveMap();
			}
			else {
				fMode = &editMode;
			}
			delete(mMapNameDialog);
		}

	}

	void saveMap() {
		if( gMap.save() ) {
			mAlert = new Alert( "map '"~gMap.name~"' saved !" );
		}
		else {
			mAlert = new Alert( "Error while saving map !", "" );
		}
		fMode = &alertMode;
		fPreviousMode = &editMode;
	}

	void mapLoadMode() {

		GUI.instance.update();
		if( mMapListDialog.done() ) {
			if( mMapListDialog.ok() && mMapListDialog.getMapName().length > 0 ) {
				delete(gMap);
				new Map(mMapListDialog.getMapName() );
				gView.setTarget( null );
			}
			fMode = &editMode;
			delete( mMapListDialog );
		}
	}

	void mapTestMode() {
		fMode = &editMode;
	}

	void alertMode() {
		GUI.instance.update();
		if( mAlert && mAlert.done() ) {
			delete( mAlert );
			fMode = fPreviousMode;
		}
	}


	void paramsMode() {
		GUI.instance.update();
		if( mParamsDialog.done() ) {

			if( mParamsDialog.ok ) {
				gMap.mName = mParamsDialog.name;
				gMap.mAuthor = mParamsDialog.author;
				gMap.mParTime = mParamsDialog.par_time;
			}

			fMode = &editMode;
			delete(mParamsDialog);
		}
	}


	GAMEPART_STATE getState() {
		return( mState );
	}


	void highlight( int x, int y, int w, int h ) {
		if( mHighlightRect.w != w || mHighlightRect.h != h || mHighlight == null ) {
			mHighlightRect.w = cast(ushort)w;
			mHighlightRect.h = cast(ushort)h;
			if( mHighlight != null ) SDL_FreeSurface( mHighlight );
			mHighlight = SDL_CreateRGBSurface( SDL_HWSURFACE, w, h, 32, 0, 0, 0, 0 );
			SDL_FillRect( mHighlight, null, 0xFFFFFFFF );
			SDL_SetAlpha( mHighlight, SDL_SRCALPHA, 128 );
		}
		mHighlightRect.x = cast(short)x;
		mHighlightRect.y = cast(short)y;
		SDL_BlitSurface( mHighlight, null, gScreen.mSurface, &mHighlightRect );
	}

}