diff options
| author | Paul Gilbert | 2010-03-23 12:02:23 +0000 | 
|---|---|---|
| committer | Paul Gilbert | 2010-03-23 12:02:23 +0000 | 
| commit | b46a2b4e100e3018d604da240cecf936c629e8a0 (patch) | |
| tree | c9cd258d0e9181a2cbaea51611971ee94d58b6b6 | |
| parent | 9571c817c7b7f30ed33ff5d4a07d80b8cea4f8c1 (diff) | |
| download | scummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.tar.gz scummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.tar.bz2 scummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.zip  | |
Added further code for the game dialog framework
svn-id: r48368
| -rw-r--r-- | engines/m4/mads_menus.cpp | 179 | ||||
| -rw-r--r-- | engines/m4/mads_menus.h | 22 | ||||
| -rw-r--r-- | engines/m4/mads_scene.cpp | 25 | ||||
| -rw-r--r-- | engines/m4/mads_scene.h | 4 | ||||
| -rw-r--r-- | engines/m4/viewmgr.cpp | 66 | ||||
| -rw-r--r-- | engines/m4/viewmgr.h | 66 | 
6 files changed, 316 insertions, 46 deletions
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index 353b41c9a9..c9cd1b129a 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -586,22 +586,32 @@ void DragonMainMenuView::handleAction(MadsGameAction action) {   *--------------------------------------------------------------------------   */ -RexDialogView::RexDialogView(): View(_madsVm, Common::Rect(0, 0, _madsVm->_screen->width(), _madsVm->_screen->height())) { +RexDialogView::RexDialogView(): MadsView(_madsVm, Common::Rect(0, 0, _madsVm->_screen->width(), _madsVm->_screen->height())) {  	_screenType = VIEWID_MENU; -	_initialised = false; +	// Store the previously active scene +	_priorSceneId = _madsVm->_scene->getCurrentScene(); + +	// Load necessary quotes +	_madsVm->globals()->loadQuoteRange(1, 48); + +	initialiseLines(); +	initialiseGraphics(); +} + +void RexDialogView::initialiseLines() {  	// Set up a list of blank entries for use in the various dialogs  	for (int i = 0; i < DIALOG_LINES_SIZE; ++i) {  		DialogTextEntry rec; +		rec.in_use = false;  		_dialogText.push_back(rec);  	}  	_totalTextEntries = 0; -	// Store the previously active scene -	_priorSceneId = _madsVm->_scene->getCurrentScene(); - -	// Load necessary quotes -	_madsVm->globals()->loadQuoteRange(1, 48); +	// Set up a default sprite slot entry +	_spriteSlotsStart = 1; +	_spriteSlots[0].spriteId = -2; +	_spriteSlots[0].timerIndex = -1;  }  void RexDialogView::initialiseGraphics() { @@ -620,20 +630,16 @@ void RexDialogView::initialiseGraphics() {  	// Set the current cursor  	_madsVm->_mouse->setCursorNum(CURSOR_ARROW); - -	_initialised = true;  }  RexDialogView::~RexDialogView() { -	if (_initialised) { -		_madsVm->_palette->deleteRange(_bgPalData); -		delete _bgPalData; -		delete _backgroundSurface; -		_madsVm->_palette->deleteRange(_spritesPalData); -		delete _spritesPalData; -		delete _menuSprites; -	} +	_madsVm->_palette->deleteRange(_bgPalData); +	delete _bgPalData; +	delete _backgroundSurface; +	_madsVm->_palette->deleteRange(_spritesPalData); +	delete _spritesPalData; +	delete _menuSprites;  }  void RexDialogView::loadBackground() { @@ -683,9 +689,6 @@ void RexDialogView::loadMenuSprites() {  void RexDialogView::updateState() { -	if (!_initialised) { -		initialiseGraphics(); -	}  }  void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) { @@ -701,11 +704,147 @@ void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) {  	View::onRefresh(rects, destSurface);  } +void RexDialogView::setFrame(int frameNumber, int depth) { +	int slotIndex = getSpriteSlotsIndex(); +	_spriteSlots[slotIndex].spriteId = 1; +	_spriteSlots[slotIndex].timerIndex = 1; +	_spriteSlots[slotIndex].spriteListIndex = 0; //_menuSpritesIndex; +	_spriteSlots[slotIndex].frameNumber = frameNumber; +	M4Sprite *spr = _menuSprites->getFrame(0); +	_spriteSlots[slotIndex].width = spr->width(); +	_spriteSlots[slotIndex].height = spr->height(); +	_spriteSlots[slotIndex].depth = depth; +	_spriteSlots[slotIndex].scale = 100; +} + +void RexDialogView::initVars() { +	_word_8502C = -1; +	_selectedLine = -1; +	_lineIndex = 0; +	_enterFlag = false; +	_textLines.clear(); +} + +void RexDialogView::addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top) { +	DialogTextEntry *rec = NULL; + +	if (_lineIndex < _totalTextEntries) { +		if (strcmp(msg_p, _dialogText[_lineIndex].text) == 0)  { +			rec = &_dialogText[_lineIndex]; +			if (rec->textDisplay_index != 0) { +				MadsTextDisplayEntry &tdEntry = _textDisplay[rec->textDisplay_index]; +				if (tdEntry.active) { +					if (_textLines.size() < 20) { +						// Add entry to line list +						_textLines.push_back(tdEntry.msg); +						tdEntry.msg = _textLines[_textLines.size() - 1].c_str(); +					} +				} +			} +		} +	} else { +		if (_lineIndex < DIALOG_LINES_SIZE) { +			rec = &_dialogText[_lineIndex]; +			_totalTextEntries = _lineIndex + 1; +		} +	} + +	// Handling for if a line needs to be added +	if (rec) { +		strcpy(rec->text, msg_p); +		rec->font = font; +		rec->field_2 = 0; +		rec->pos.y = top; +		rec->widthAdjust = -1; +		rec->in_use = true; +		rec->textDisplay_index = -1; + +		switch (alignment) { +		case ALIGN_CENTER: +			// Center text +			rec->pos.x = (width() - font->getWidth(rec->text)) / 2; +			break; + +		case ALIGN_CHAR_CENTER: { +			// Text is center aligned on the '@' character within the string +			char *p = strchr(rec->text, '@'); + +			if (p) { +				// '@' string handling +				// Get length of string up to the '@' character +				*p = '\0'; +				int strWidth = font->getWidth(rec->text, rec->widthAdjust); +				// Remove the character from the string. strcpy isn't used here because it's unsafe for +				// copying within the same string +				while ((*p == *(p + 1)) != '\0') ++p; + +				rec->pos.x = (width() / 2) - strWidth; +			} else { +				rec->pos.x = left; +			} +			break; +		} +	 +		case RIGHT_ALIGN: +			// Right align (moving left from given passed left) +			rec->pos.x = left - font->getWidth(rec->text); +			break; + +		default: +			break; +		} +	} + +	++_lineIndex; +} + +/** + * Adds a line consisting of either a single quote, or the combination of two quote Ids + */ +void RexDialogView::addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2) { +	char buffer[80]; + +	// Copy the first quote string into the buffer +	const char *quoteStr = _madsVm->globals()->getQuote(id1); +	strcpy(buffer, quoteStr); + +	// Handle the optional second quote Id +	if (id2 != 0) { +		quoteStr = _madsVm->globals()->getQuote(id2); +		strcat(buffer, " "); +		strcat(buffer, quoteStr); +	} + +	// Add in the generated line +	addLine(buffer, font, alignment, left, top); +} +  /*--------------------------------------------------------------------------   * RexDialogView is the Rex Nebular Game Menu dialog   *--------------------------------------------------------------------------   */ +RexGameMenuDialog::RexGameMenuDialog(): RexDialogView() { +	setFrame(1, 2); +	initVars(); + +	_vm->_font->setFont(FONT_CONVERSATION_MADS); +	addLines(); +} + +void RexGameMenuDialog::addLines() { +	// Add the title +	int top = -((_vm->_font->getHeight() + 1) * 12 - 78); +	addQuote(_vm->_font, ALIGN_CENTER, 0, top, 10); + +	// Loop for adding the option lines of the dialog +	top += 6; +	for (int idx = 0; idx < 5; ++idx) { +		top += _vm->_font->getHeight() + 1; +		addQuote(_vm->_font, ALIGN_CENTER, 0, top, 11 + idx); +	} +} +  void RexGameMenuDialog::onRefresh(RectList *rects, M4Surface *destSurface) {  	RexDialogView::onRefresh(rects, destSurface);  } diff --git a/engines/m4/mads_menus.h b/engines/m4/mads_menus.h index 0fad0cfb76..5d3258ab46 100644 --- a/engines/m4/mads_menus.h +++ b/engines/m4/mads_menus.h @@ -104,15 +104,29 @@ public:  #define DIALOG_LINES_SIZE 20 -class RexDialogView: public View { +enum MadsTextAlignment { ALIGN_CENTER = -1, ALIGN_CHAR_CENTER = -2, RIGHT_ALIGN = -3 }; + + +class RexDialogView: public MadsView {  private:  	int _priorSceneId; -	bool _initialised; +	void initialiseLines();  	void initialiseGraphics();  	void loadBackground();  	void loadMenuSprites();  protected: +	int _word_8502C; +	int _selectedLine; +	int _lineIndex; +	bool _enterFlag; +	Common::StringArray _textLines; + +	void setFrame(int frameNumber, int depth); +	void initVars(); +	void addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top); +	void addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2 = 0); +protected:  	M4Surface *_backgroundSurface;  	RGBList *_bgPalData;  	SpriteAsset *_menuSprites; @@ -131,8 +145,10 @@ public:  };  class RexGameMenuDialog: public RexDialogView { +private: +	void addLines();  public: -	RexGameMenuDialog(): RexDialogView() {}; +	RexGameMenuDialog();  	virtual void onRefresh(RectList *rects, M4Surface *destSurface);  }; diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index df5e6ba220..53f232472d 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -688,7 +688,7 @@ void MadsSceneResources::load(int sId) {  /*--------------------------------------------------------------------------*/  MadsScreenText::MadsScreenText() { -	for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) +	for (int i = 0; i < OLD_TEXT_DISPLAY_SIZE; ++i)  		_textDisplay[i].active = false;  	for (int i = 0; i < TIMED_TEXT_SIZE; ++i)  		_timedText[i].flags = 0; @@ -701,9 +701,9 @@ MadsScreenText::MadsScreenText() {  int MadsScreenText::add(const Common::Point &destPos, uint fontColours, int widthAdjust, const char *msg, Font *font) {  	// Find a free slot  	int idx = 0; -	while ((idx < TEXT_DISPLAY_SIZE) && _textDisplay[idx].active) +	while ((idx < OLD_TEXT_DISPLAY_SIZE) && _textDisplay[idx].active)  		++idx; -	if (idx == TEXT_DISPLAY_SIZE) +	if (idx == OLD_TEXT_DISPLAY_SIZE)  		error("Ran out of text display slots");  	// Set up the entry values @@ -766,27 +766,10 @@ int MadsScreenText::addTimed(const Common::Point &destPos, uint fontColours, uin   * Draws any text display entries to the screen   */  void MadsScreenText::draw(M4Surface *surface) { -	for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { -		if (_textDisplay[idx].active && (_textDisplay[idx].active2 >= 0)) { -			_textDisplay[idx].font->setColours(_textDisplay[idx].colour1, 0xFF, -				(_textDisplay[idx].colour2 == 0) ? _textDisplay[idx].colour1 : _textDisplay[idx].colour2); -			_textDisplay[idx].font->writeString(surface, _textDisplay[idx].message,  -				_textDisplay[idx].bounds.left, _textDisplay[idx].bounds.top, _textDisplay[idx].bounds.width(), -				_textDisplay[idx].spacing); -		} -	} - -	// Clear up any now inactive text display entries -	for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { -		if (_textDisplay[idx].active2 < 0) { -			_textDisplay[idx].active = false; -			_textDisplay[idx].active2 = 0; -		} -	}  }  void MadsScreenText::timedDisplay() { -	for (int idx = 0; !_abortTimedText && (idx < TEXT_DISPLAY_SIZE); ++idx) { +	for (int idx = 0; !_abortTimedText && (idx < OLD_TEXT_DISPLAY_SIZE); ++idx) {  		if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&   			(_timedText[idx].frameTimer <= g_system->getMillis()))  			// Add the specified entry diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index d5d3a5a477..b4cdbafd80 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -66,7 +66,7 @@ public:  };  #define TIMED_TEXT_SIZE 10 -#define TEXT_DISPLAY_SIZE 40 +#define OLD_TEXT_DISPLAY_SIZE 40  #define TEXT_4A_SIZE 30  enum TalkTextFlags {TEXTFLAG_2 = 2, TEXTFLAG_4 = 4, TEXTFLAG_8 = 8, TEXTFLAG_40 = 0x40, @@ -104,7 +104,7 @@ struct Text4A {  class MadsScreenText {  private: -	TextDisplay _textDisplay[TEXT_DISPLAY_SIZE]; +	TextDisplay _textDisplay[OLD_TEXT_DISPLAY_SIZE];  	TimedText _timedText[TIMED_TEXT_SIZE];  	Text4A _text4A[TEXT_4A_SIZE];  	bool _abortTimedText; diff --git a/engines/m4/viewmgr.cpp b/engines/m4/viewmgr.cpp index 46b4b5af9d..a1e9c3e584 100644 --- a/engines/m4/viewmgr.cpp +++ b/engines/m4/viewmgr.cpp @@ -194,6 +194,72 @@ void View::onRefresh(RectList *rects, M4Surface *destSurface) {  //-------------------------------------------------------------------------- +MadsTextDisplay::MadsTextDisplay() { +	for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) +		_entries[i].active = false; +} + +int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font) { +	int usedSlot = -1; + +	for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { +		if (!_entries[idx].active) { +			usedSlot = idx; + +			_entries[idx].bounds.left = xp; +			_entries[idx].bounds.top = yp; +			_entries[idx].font = font; +			_entries[idx].msg = msg; +			_entries[idx].bounds.setWidth(font->getWidth(msg, charSpacing)); +			_entries[idx].bounds.setHeight(font->getHeight()); +			_entries[idx].colour1 = fontColour & 0xff; +			_entries[idx].colour2 = fontColour >> 8; +			_entries[idx].spacing = charSpacing; +			_entries[idx].active2 = 1; +			_entries[idx].active = true; +			break; +		} +	} + +	return usedSlot; +} + +void MadsTextDisplay::draw(View *view) { +	for (int idx = 0; idx < OLD_TEXT_DISPLAY_SIZE; ++idx) { +		if (_entries[idx].active && (_entries[idx].active2 >= 0)) { +			_entries[idx].font->setColours(_entries[idx].colour1, 0xFF, +				(_entries[idx].colour2 == 0) ? _entries[idx].colour1 : _entries[idx].colour2); +			_entries[idx].font->writeString(view, _entries[idx].msg,  +				_entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(), +				_entries[idx].spacing); +		} +	} + +	// Clear up any now inactive text display entries +	for (int idx = 0; idx < OLD_TEXT_DISPLAY_SIZE; ++idx) { +		if (_entries[idx].active2 < 0) { +			_entries[idx].active = false; +			_entries[idx].active2 = 0; +		} +	} +} + +//-------------------------------------------------------------------------- + +MadsView::MadsView(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent): View(vm, viewBounds, transparent) { +	_spriteSlotsStart = 0; +} + +MadsView::MadsView(MadsM4Engine *vm, int x, int y, bool transparent): View(vm, x, y, transparent) { +	_spriteSlotsStart = 0; +} + +int MadsView::getSpriteSlotsIndex() { +	return _spriteSlotsStart++; +} + +//-------------------------------------------------------------------------- +  ViewManager::ViewManager(MadsM4Engine *vm): _systemHotkeys(HotkeyList(NULL)), _vm(vm) {  	_captureScreen = NULL;  	_captureEvents = false; diff --git a/engines/m4/viewmgr.h b/engines/m4/viewmgr.h index dccfffb8aa..308240645d 100644 --- a/engines/m4/viewmgr.h +++ b/engines/m4/viewmgr.h @@ -32,6 +32,7 @@  #include "common/events.h"  #include "common/rect.h" +#include "m4/font.h"  #include "m4/globals.h"  #include "m4/events.h"  #include "m4/graphics.h" @@ -147,6 +148,71 @@ protected:  	bool _transparent;  }; +class MadsSpriteSlot { +public: +	int spriteId; +	int timerIndex; +	int spriteListIndex; +	int frameNumber; +	int width; +	int height; +	int depth; +	int scale; + +	MadsSpriteSlot() { }; +}; + +#define SPRITE_SLOTS_SIZE 50 + +class MadsTextDisplayEntry { +public: +	bool active; +	int spacing; +	Common::Rect bounds; +	int active2; +	uint8 colour1; +	uint8 colour2; +	Font *font; +	const char *msg; + +	MadsTextDisplayEntry() { active = false; } +}; + +#define TEXT_DISPLAY_SIZE 40 + +class MadsTextDisplay { +private: +	MadsTextDisplayEntry _entries[TEXT_DISPLAY_SIZE]; +public: +	MadsTextDisplay(); + +	MadsTextDisplayEntry &operator[](int idx) { +		assert(idx < TEXT_DISPLAY_SIZE); +		return _entries[idx]; +	} + +	int setActive2(int idx) { +		assert(idx < TEXT_DISPLAY_SIZE); +		_entries[idx].active2 = -1; +	} + +	int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font); +	void draw(View *view); +}; + +class MadsView: public View { +protected: +	MadsSpriteSlot _spriteSlots[SPRITE_SLOTS_SIZE]; +	MadsTextDisplay _textDisplay; +	int _spriteSlotsStart; + +	int getSpriteSlotsIndex(); +public: +	MadsView(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent = false); +	MadsView(MadsM4Engine *vm, int x = 0, int y = 0, bool transparent = false); + +}; +  class ViewManager {  private:  	MadsM4Engine *_vm;  | 
