Changeset - r13124:e645e6b06ab7
[Not reviewed]
master
0 1 0
rubidium - 15 years ago 2009-09-26 08:30:02
rubidium@openttd.org
(svn r17639) -Codechange: let the difficulty settings GUI make really use the nested widget features
1 file changed with 149 insertions and 110 deletions:
0 comments (0 inline, 0 general)
src/settings_gui.cpp
Show inline comments
 
@@ -518,143 +518,135 @@ enum GameDifficultyWidgets {
 
	GDW_LVL_CUSTOM,
 
	GDW_HIGHSCORE,
 
	GDW_SETTING_BG,
 
	GDW_LOWER_BG,
 
	GDW_ACCEPT,
 
	GDW_CANCEL,
 

	
 
	GDW_OPTIONS_START,
 
};
 

	
 
void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
 

	
 
struct GameDifficultyWindow : public Window {
 
class GameDifficultyWindow : public Window {
 
private:
 
	static const uint GAME_DIFFICULTY_NUM = 18;
 
	bool clicked_increase;
 
	uint8 clicked_button;
 
	uint8 timeout;
 

	
 
	/* Temporary holding place of values in the difficulty window until 'Save' is clicked */
 
	GameSettings opt_mod_temp;
 

	
 
	enum {
 
		GAMEDIFF_WND_TOP_OFFSET = 45,
 
		GAMEDIFF_WND_ROWSIZE    = 9,
 
		NO_SETTINGS_BUTTON = 0xFF,
 
	};
 
public:
 
	/** The number of difficulty settings */
 
	static const uint GAME_DIFFICULTY_NUM = 18;
 
	/** The number of widgets per difficulty setting */
 
	static const uint WIDGETS_PER_DIFFICULTY = 3;
 

	
 
public:
 
	GameDifficultyWindow(const WindowDesc *desc) : Window()
 
	{
 
		this->InitNested(desc);
 

	
 
		/* Copy current settings (ingame or in intro) to temporary holding place
 
		 * change that when setting stuff, copy back on clicking 'OK' */
 
		this->opt_mod_temp = (_game_mode == GM_MENU) ? _settings_newgame : _settings_game;
 
		this->clicked_increase = false;
 
		this->clicked_button = NO_SETTINGS_BUTTON;
 
		this->timeout = 0;
 
		/* Setup disabled buttons when creating window
 
		 * disable all other difficulty buttons during gameplay except for 'custom' */
 
		this->SetWidgetsDisabledState(_game_mode == GM_NORMAL,
 
			GDW_LVL_EASY,
 
			GDW_LVL_MEDIUM,
 
			GDW_LVL_HARD,
 
			GDW_LVL_CUSTOM,
 
			WIDGET_LIST_END);
 
		this->SetWidgetDisabledState(GDW_HIGHSCORE, _game_mode == GM_EDITOR || _networking); // highscore chart in multiplayer
 
		this->SetWidgetDisabledState(GDW_ACCEPT, _networking && !_network_server); // Save-button in multiplayer (and if client)
 
		this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 
		this->OnInvalidateData();
 
	}
 

	
 
	virtual void SetStringParameters(int widget) const
 
	{
 
		widget -= GDW_OPTIONS_START;
 
		if (widget < 0 || (widget % 3) != 2) return;
 

	
 
		widget /= 3;
 

	
 
		uint i;
 
		const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + widget;
 
		int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
		SetDParam(0, sd->desc.str + value);
 
	}
 

	
 
	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
 
	{
 
		/* Only for the 'descriptions' */
 
		int index = widget - GDW_OPTIONS_START;
 
		if (index < 0 || (index % 3) != 2) return;
 

	
 
		index /= 3;
 

	
 
		uint i;
 
		const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + index;
 
		const SettingDescBase *sdb = &sd->desc;
 

	
 
		/* Get the string and try all strings from the smallest to the highest value */
 
		StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
 
		for (int32 value = sdb->min; (uint32)value <= sdb->max; value += sdb->interval) {
 
			SetDParam(0, sdb->str + value);
 
			*size = maxdim(*size, GetStringBoundingBox(str));
 
		}
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 

	
 
		uint i;
 
		const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i);
 
		int y = GAMEDIFF_WND_TOP_OFFSET;
 
		StringID str = STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS;
 
		for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) {
 
			const SettingDescBase *sdb = &sd->desc;
 
			/* skip deprecated difficulty options */
 
			if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
 
			int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
			bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
 

	
 
			DrawArrowButtons(5, y, COLOUR_YELLOW,
 
					(this->clicked_button == i) ? 1 + !!this->clicked_increase : 0,
 
					editable && sdb->min != value,
 
					editable && sdb->max != (uint32)value);
 

	
 
			value += sdb->str;
 
			SetDParam(0, value);
 
			DrawString(30, this->width, y, str);
 

	
 
			y += GAMEDIFF_WND_ROWSIZE + 2; // space items apart a bit
 
			str++;
 
		}
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case GDW_SETTING_BG: { // Difficulty settings widget, decode click
 
				/* Don't allow clients to make any changes */
 
				if (_networking && !_network_server) return;
 
		if (widget >= GDW_OPTIONS_START) {
 
			widget -= GDW_OPTIONS_START;
 
			if ((widget % 3) == 2) return;
 

	
 
				const int x = pt.x - 5;
 
				if (!IsInsideMM(x, 0, 21)) return; // Button area
 
			/* Don't allow clients to make any changes */
 
			if (_networking && !_network_server) return;
 

	
 
				const int y = pt.y - GAMEDIFF_WND_TOP_OFFSET;
 
				if (y < 0) return;
 
			uint i;
 
			const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + (widget / 3);
 
			const SettingDescBase *sdb = &sd->desc;
 

	
 
				/* Get button from Y coord. */
 
				uint8 btn = y / (GAMEDIFF_WND_ROWSIZE + 2);
 
				if (btn >= 1) btn++; // Skip the deprecated option "competitor start time"
 
				if (btn >= 8) btn++; // Skip the deprecated option "competitor intelligence"
 
				if (btn >= GAME_DIFFICULTY_NUM || y % (GAMEDIFF_WND_ROWSIZE + 2) >= 9) return;
 

	
 
				uint i;
 
				const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + btn;
 
				const SettingDescBase *sdb = &sd->desc;
 
			/* Clicked disabled button? */
 
			bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
 
			if (!editable) return;
 

	
 
				/* Clicked disabled button? */
 
				bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
 
				if (!editable) return;
 

	
 
				this->timeout = 5;
 
				int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
			int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
			if (widget % 3 == 1) {
 
				/* Increase button clicked */
 
				val = min(val + sdb->interval, (int32)sdb->max);
 
			} else {
 
				/* Decrease button clicked */
 
				val -= sdb->interval;
 
				val = max(val, sdb->min);
 
			}
 

	
 
				if (x >= 10) {
 
					/* Increase button clicked */
 
					val = min(val + sdb->interval, (int32)sdb->max);
 
					this->clicked_increase = true;
 
				} else {
 
					/* Decrease button clicked */
 
					val -= sdb->interval;
 
					val = max(val, sdb->min);
 
					this->clicked_increase = false;
 
				}
 
				this->clicked_button = btn;
 
			/* save value in temporary variable */
 
			WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val);
 
			this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 
			SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom
 
			this->LowerWidget(GDW_LVL_CUSTOM);
 
			this->OnInvalidateData();
 
			this->SetDirty();
 
			return;
 
		}
 

	
 
				/* save value in temporary variable */
 
				WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val);
 
				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 
				SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom
 
				this->LowerWidget(GDW_LVL_CUSTOM);
 
				this->SetDirty();
 
			} break;
 

	
 
		switch (widget) {
 
			case GDW_LVL_EASY:
 
			case GDW_LVL_MEDIUM:
 
			case GDW_LVL_HARD:
 
			case GDW_LVL_CUSTOM:
 
				/* temporarily change difficulty level */
 
				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 
				SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp.difficulty);
 
				this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 
				this->OnInvalidateData();
 
				this->SetDirty();
 
				break;
 

	
 
			case GDW_HIGHSCORE: // Highscore Table
 
				ShowHighscoreTable(this->opt_mod_temp.difficulty.diff_level, -1);
 
				break;
 
@@ -686,61 +678,108 @@ public:
 
			case GDW_CANCEL: // Cancel button - close window, abandon changes
 
				delete this;
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnTick()
 
	virtual void OnInvalidateData(int data = 0)
 
	{
 
		if (this->timeout != 0) {
 
			this->timeout--;
 
			if (this->timeout == 0) this->clicked_button = NO_SETTINGS_BUTTON;
 
			this->SetDirty();
 
		uint i;
 
		const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i);
 
		for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) {
 
			const SettingDescBase *sdb = &sd->desc;
 
			/* skip deprecated difficulty options */
 
			if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
 
			int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
			bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
 

	
 
			this->SetWidgetDisabledState(GDW_OPTIONS_START + i * 3 + 0, !editable || sdb->min == value);
 
			this->SetWidgetDisabledState(GDW_OPTIONS_START + i * 3 + 1, !editable || sdb->max == (uint32)value);
 
		}
 
	}
 
};
 

	
 
static NWidgetBase *MakeDifficultyOptionsWidgets(int *biggest_index)
 
{
 
	NWidgetVertical *vert_desc = new NWidgetVertical;
 

	
 
	int widnum = GDW_OPTIONS_START;
 
	uint i, j;
 
	const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i);
 

	
 
	for (i = 0, j = 0; i < GameDifficultyWindow::GAME_DIFFICULTY_NUM; i++, sd++, widnum += GameDifficultyWindow::WIDGETS_PER_DIFFICULTY) {
 
		if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
 

	
 
		NWidgetHorizontal *hor = new NWidgetHorizontal;
 

	
 
		/* [<] button. */
 
		NWidgetLeaf *leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_YELLOW, widnum, STR_BLACK_SMALL_ARROW_LEFT, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST);
 
		hor->Add(leaf);
 

	
 
		/* [>] button. */
 
		leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_YELLOW, widnum + 1, STR_BLACK_SMALL_ARROW_RIGHT, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST);
 
		hor->Add(leaf);
 

	
 
		/* Some spacing between the text and the description */
 
		NWidgetSpacer *spacer = new NWidgetSpacer(5, 0);
 
		hor->Add(spacer);
 

	
 
		/* Descriptive text. */
 
		leaf = new NWidgetLeaf(WWT_TEXT, COLOUR_YELLOW, widnum + 2, STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS + (j++), STR_NULL);
 
		leaf->SetFill(true, false);
 
		hor->Add(leaf);
 
		vert_desc->Add(hor);
 

	
 
		/* Space vertically */
 
		vert_desc->Add(new NWidgetSpacer(0, 2));
 
	}
 
	*biggest_index = widnum - 1;
 
	return vert_desc;
 
}
 

	
 

	
 
/** Widget definition for the game difficulty settings window */
 
static const NWidgetPart _nested_game_difficulty_widgets[] = {
 
	NWidget(WWT_CAPTION, COLOUR_MAUVE, GDW_CAPTION), SetMinimalSize(370, 14), SetDataTip(STR_DIFFICULTY_LEVEL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	NWidget(WWT_CAPTION, COLOUR_MAUVE, GDW_CAPTION), SetDataTip(STR_DIFFICULTY_LEVEL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_UPPER_BG),
 
		NWidget(NWID_SPACER), SetMinimalSize(0, 2),
 
		NWidget(NWID_HORIZONTAL),
 
			NWidget(NWID_SPACER), SetMinimalSize(10, 0),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_EASY), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_EASY, STR_NULL),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_MEDIUM), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_MEDIUM, STR_NULL),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_HARD), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_HARD, STR_NULL),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_CUSTOM), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_CUSTOM, STR_NULL),
 
			NWidget(NWID_SPACER), SetMinimalSize(12, 0),
 
		NWidget(NWID_VERTICAL), SetPIP(2, 0, 2),
 
			NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10),
 
				NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_EASY), SetDataTip(STR_DIFFICULTY_LEVEL_EASY, STR_NULL), SetFill(true, false),
 
				NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_MEDIUM), SetDataTip(STR_DIFFICULTY_LEVEL_MEDIUM, STR_NULL), SetFill(true, false),
 
				NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_HARD), SetDataTip(STR_DIFFICULTY_LEVEL_HARD, STR_NULL), SetFill(true, false),
 
				NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_CUSTOM), SetDataTip(STR_DIFFICULTY_LEVEL_CUSTOM, STR_NULL), SetFill(true, false),
 
			EndContainer(),
 
			NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10),
 
				NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, GDW_HIGHSCORE), SetDataTip(STR_DIFFICULTY_LEVEL_HIGH_SCORE_BUTTON, STR_NULL), SetFill(true, false),
 
			EndContainer(),
 
		EndContainer(),
 
		NWidget(NWID_HORIZONTAL),
 
			NWidget(NWID_SPACER), SetMinimalSize(10, 0),
 
			NWidget(WWT_TEXTBTN, COLOUR_GREEN, GDW_HIGHSCORE), SetMinimalSize(348, 12), SetDataTip(STR_DIFFICULTY_LEVEL_HIGH_SCORE_BUTTON, STR_NULL),
 
			NWidget(NWID_SPACER), SetMinimalSize(12, 0),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_SETTING_BG),
 
		NWidget(NWID_VERTICAL), SetPIP(3, 0, 1),
 
			NWidget(NWID_HORIZONTAL), SetPIP(5, 0, 5),
 
				NWidgetFunction(MakeDifficultyOptionsWidgets),
 
			EndContainer(),
 
		EndContainer(),
 
		NWidget(NWID_SPACER), SetMinimalSize(0, 2),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_SETTING_BG), SetMinimalSize(370, 221),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_LOWER_BG),
 
		NWidget(NWID_SPACER), SetMinimalSize(0, 2),
 
		NWidget(NWID_HORIZONTAL),
 
			NWidget(NWID_SPACER), SetMinimalSize(105, 0),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_ACCEPT), SetMinimalSize(81, 12), SetDataTip(STR_DIFFICULTY_LEVEL_SAVE, STR_NULL),
 
			NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_CANCEL), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
 
			NWidget(NWID_SPACER), SetMinimalSize(103, 0),
 
		NWidget(NWID_VERTICAL), SetPIP(2, 0, 2),
 
			NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10),
 
				NWidget(NWID_SPACER), SetFill(true, false),
 
				NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_ACCEPT), SetDataTip(STR_DIFFICULTY_LEVEL_SAVE, STR_NULL), SetFill(true, false),
 
				NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_CANCEL), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), SetFill(true, false),
 
				NWidget(NWID_SPACER), SetFill(true, false),
 
			EndContainer(),
 
		EndContainer(),
 
		NWidget(NWID_SPACER), SetMinimalSize(0, 2),
 
	EndContainer(),
 
};
 

	
 
/** Window definition for the game difficulty settings window */
 
static const WindowDesc _game_difficulty_desc(
 
	WDP_CENTER, WDP_CENTER, 370, 279, 370, 279,
 
	WC_GAME_OPTIONS, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
	NULL, _nested_game_difficulty_widgets, lengthof(_nested_game_difficulty_widgets)
 
);
 

	
 
void ShowGameDifficulty()
 
{
 
	DeleteWindowById(WC_GAME_OPTIONS, 0);
0 comments (0 inline, 0 general)