|
@@ -624,32 +624,36 @@ struct PatchEntry {
|
|
|
byte flags; ///< Flags of the patch entry. @see PatchEntryFlags
|
|
|
byte level; ///< Nesting level of this patch entry
|
|
|
union {
|
|
|
PatchEntrySetting entry; ///< Data fields if entry is a setting
|
|
|
PatchEntrySubtree sub; ///< Data fields if entry is a sub-page
|
|
|
} d; ///< Data fields for each kind
|
|
|
|
|
|
PatchEntry(const char *nm);
|
|
|
PatchEntry(PatchPage *sub, StringID title);
|
|
|
|
|
|
void Init(byte level, bool last_field);
|
|
|
void SetButtons(byte new_val);
|
|
|
|
|
|
uint Length() const;
|
|
|
};
|
|
|
|
|
|
/** Data structure describing one page of patches in the patch settings window. */
|
|
|
struct PatchPage {
|
|
|
PatchEntry *entries; ///< Array of patch entries of the page.
|
|
|
byte num; ///< Number of entries on the page (statically filled).
|
|
|
|
|
|
void Init(byte level = 0);
|
|
|
|
|
|
uint Length() const;
|
|
|
};
|
|
|
|
|
|
|
|
|
/* == PatchEntry methods == */
|
|
|
|
|
|
/**
|
|
|
* Constructor for a single setting in the 'advanced settings' window
|
|
|
* @param nm Name of the setting in the setting table
|
|
|
*/
|
|
|
PatchEntry::PatchEntry(const char *nm)
|
|
|
{
|
|
|
this->flags = PEF_SETTING_KIND;
|
|
@@ -697,38 +701,62 @@ void PatchEntry::Init(byte level, bool l
|
|
|
|
|
|
/**
|
|
|
* Set the button-depressed flags (#PEF_LEFT_DEPRESSED and #PEF_RIGHT_DEPRESSED) to a specified value
|
|
|
* @param new_val New value for the button flags
|
|
|
* @see PatchEntryFlags
|
|
|
*/
|
|
|
void PatchEntry::SetButtons(byte new_val)
|
|
|
{
|
|
|
assert((new_val & ~PEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
|
|
|
this->flags = (this->flags & ~PEF_BUTTONS_MASK) | new_val;
|
|
|
}
|
|
|
|
|
|
/** Return numbers of rows needed to display the entry */
|
|
|
uint PatchEntry::Length() const
|
|
|
{
|
|
|
switch(this->flags & PEF_KIND_MASK) {
|
|
|
case PEF_SETTING_KIND:
|
|
|
return 1;
|
|
|
case PEF_SUBTREE_KIND:
|
|
|
if (this->d.sub.folded) return 1; // Only displaying the title
|
|
|
|
|
|
return 1 + this->d.sub.page->Length(); // 1 extra row for the title
|
|
|
default: NOT_REACHED();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/* == PatchPage methods == */
|
|
|
|
|
|
/**
|
|
|
* Initialization of an entire setting page
|
|
|
* @param level Nesting level of this page (internal variable, do not provide a value for it when calling)
|
|
|
*/
|
|
|
void PatchPage::Init(byte level)
|
|
|
{
|
|
|
for (uint field = 0; field < this->num; field++) {
|
|
|
this->entries[field].Init(level, field + 1 == num);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Return number of rows needed to display the whole page */
|
|
|
uint PatchPage::Length() const
|
|
|
{
|
|
|
uint length = 0;
|
|
|
for (uint field = 0; field < this->num; field++) {
|
|
|
length += this->entries[field].Length();
|
|
|
}
|
|
|
return length;
|
|
|
}
|
|
|
|
|
|
|
|
|
static PatchEntry _patches_ui[] = {
|
|
|
PatchEntry("gui.vehicle_speed"),
|
|
|
PatchEntry("gui.status_long_date"),
|
|
|
PatchEntry("gui.date_format_in_default_names"),
|
|
|
PatchEntry("gui.show_finances"),
|
|
|
PatchEntry("gui.autoscroll"),
|
|
|
PatchEntry("gui.reverse_scroll"),
|
|
|
PatchEntry("gui.smooth_scroll"),
|
|
|
PatchEntry("gui.errmsg_duration"),
|
|
|
PatchEntry("gui.toolbar_pos"),
|
|
|
PatchEntry("gui.measure_tooltip"),
|
|
@@ -900,46 +928,46 @@ struct PatchesSelectionWindow : Window {
|
|
|
/* Build up the dynamic settings-array only once per OpenTTD session */
|
|
|
if (first_time) {
|
|
|
for (PatchPage *page = &_patches_page[0]; page != endof(_patches_page); page++) {
|
|
|
page->Init();
|
|
|
}
|
|
|
first_time = false;
|
|
|
}
|
|
|
|
|
|
this->page = 0;
|
|
|
this->clicked_entry = NULL; // No numeric patch setting buttons are depressed
|
|
|
this->vscroll.pos = 0;
|
|
|
this->vscroll.cap = (this->widget[PATCHSEL_OPTIONSPANEL].bottom - this->widget[PATCHSEL_OPTIONSPANEL].top - 8) / SETTING_HEIGHT;
|
|
|
SetVScrollCount(this, _patches_page[this->page].num);
|
|
|
SetVScrollCount(this, _patches_page[this->page].Length());
|
|
|
|
|
|
this->resize.step_height = SETTING_HEIGHT;
|
|
|
this->resize.height = this->height;
|
|
|
this->resize.step_width = 1;
|
|
|
this->resize.width = this->width;
|
|
|
|
|
|
this->LowerWidget(this->page + PATCHSEL_INTERFACE); // Depress button of currently selected page
|
|
|
|
|
|
this->FindWindowPlacementAndResize(desc);
|
|
|
}
|
|
|
|
|
|
virtual void OnPaint()
|
|
|
{
|
|
|
const PatchPage *page = &_patches_page[this->page];
|
|
|
|
|
|
/* Set up selected category */
|
|
|
this->DrawWidgets();
|
|
|
|
|
|
int x = SETTINGTREE_LEFT_OFFSET;
|
|
|
int y = SETTINGTREE_TOP_OFFSET;
|
|
|
for (uint i = this->vscroll.pos; i != page->num && this->vscroll.pos + this->vscroll.cap - i > 0; i++) {
|
|
|
for (uint i = this->vscroll.pos; i != page->Length() && this->vscroll.pos + this->vscroll.cap - i > 0; i++) {
|
|
|
assert((page->entries[i].flags & PEF_KIND_MASK) == PEF_SETTING_KIND);
|
|
|
const SettingDesc *sd = page->entries[i].d.entry.setting;
|
|
|
int state = page->entries[i].flags & PEF_BUTTONS_MASK;
|
|
|
DrawPatch(patches_ptr, sd, x, y, state);
|
|
|
y += SETTING_HEIGHT;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void DrawPatch(GameSettings *patches_ptr, const SettingDesc *sd, int x, int y, int state)
|
|
|
{
|
|
|
const SettingDescBase *sdb = &sd->desc;
|
|
|
const void *var = GetVariableAddress(patches_ptr, &sd->save);
|
|
@@ -989,25 +1017,25 @@ struct PatchesSelectionWindow : Window {
|
|
|
case PATCHSEL_OPTIONSPANEL: {
|
|
|
int y = pt.y - SETTINGTREE_TOP_OFFSET; // Shift y coordinate
|
|
|
if (y < 0) return; // Clicked above first entry
|
|
|
|
|
|
int x = pt.x - SETTINGTREE_LEFT_OFFSET; // Shift x coordinate
|
|
|
if (x < 0) return; // Clicked left of the entry
|
|
|
|
|
|
byte btn = this->vscroll.pos + y / SETTING_HEIGHT; // Compute which setting is selected
|
|
|
if (y % SETTING_HEIGHT > SETTING_HEIGHT - 2) return; // Clicked too low at the setting
|
|
|
|
|
|
const PatchPage *page = &_patches_page[this->page];
|
|
|
|
|
|
if (btn >= page->num) return; // Clicked below the last setting of the page
|
|
|
if (btn >= page->Length()) return; // Clicked below the last setting of the page
|
|
|
|
|
|
assert((page->entries[btn].flags & PEF_KIND_MASK) == PEF_SETTING_KIND);
|
|
|
const SettingDesc *sd = page->entries[btn].d.entry.setting;
|
|
|
|
|
|
/* return if action is only active in network, or only settable by server */
|
|
|
if (!(sd->save.conv & SLF_NETWORK_NO) && _networking && !_network_server) return;
|
|
|
if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return;
|
|
|
if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return;
|
|
|
|
|
|
void *var = GetVariableAddress(patches_ptr, &sd->save);
|
|
|
int32 value = (int32)ReadValue(var, sd->save.conv);
|
|
|
|
|
@@ -1070,25 +1098,25 @@ struct PatchesSelectionWindow : Window {
|
|
|
this->entry = btn;
|
|
|
SetDParam(0, value);
|
|
|
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_PATCHES_QUERY_CAPT, 10, 100, this, CS_NUMERAL, QSF_NONE);
|
|
|
}
|
|
|
}
|
|
|
} break;
|
|
|
|
|
|
case PATCHSEL_INTERFACE: case PATCHSEL_CONSTRUCTION: case PATCHSEL_VEHICLES:
|
|
|
case PATCHSEL_STATIONS: case PATCHSEL_ECONOMY: case PATCHSEL_COMPETITORS:
|
|
|
this->RaiseWidget(this->page + PATCHSEL_INTERFACE);
|
|
|
this->page = widget - PATCHSEL_INTERFACE;
|
|
|
this->LowerWidget(this->page + PATCHSEL_INTERFACE);
|
|
|
SetVScrollCount(this, _patches_page[this->page].num);
|
|
|
SetVScrollCount(this, _patches_page[this->page].Length());
|
|
|
DeleteWindowById(WC_QUERY_STRING, 0);
|
|
|
this->SetDirty();
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
virtual void OnTimeout()
|
|
|
{
|
|
|
if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
|
|
|
this->clicked_entry->SetButtons(0);
|
|
|
this->clicked_entry = NULL;
|
|
|
this->SetDirty();
|
|
@@ -1105,25 +1133,25 @@ struct PatchesSelectionWindow : Window {
|
|
|
|
|
|
/* Save the correct currency-translated value */
|
|
|
if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
|
|
|
|
|
|
SetPatchValue(pe->d.entry.index, value);
|
|
|
this->SetDirty();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
virtual void OnResize(Point new_size, Point delta)
|
|
|
{
|
|
|
this->vscroll.cap += delta.y / SETTING_HEIGHT;
|
|
|
SetVScrollCount(this, _patches_page[this->page].num);
|
|
|
SetVScrollCount(this, _patches_page[this->page].Length());
|
|
|
}
|
|
|
};
|
|
|
|
|
|
GameSettings *PatchesSelectionWindow::patches_ptr = NULL;
|
|
|
const int PatchesSelectionWindow::SETTINGTREE_LEFT_OFFSET = 5;
|
|
|
const int PatchesSelectionWindow::SETTINGTREE_TOP_OFFSET = 47;
|
|
|
|
|
|
static const Widget _patches_selection_widgets[] = {
|
|
|
{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_MAUVE, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
|
|
{ WWT_CAPTION, RESIZE_RIGHT, COLOUR_MAUVE, 11, 381, 0, 13, STR_CONFIG_PATCHES_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
|
|
{ WWT_PANEL, RESIZE_RIGHT, COLOUR_MAUVE, 0, 381, 14, 41, 0x0, STR_NULL},
|
|
|
{ WWT_PANEL, RESIZE_RB, COLOUR_MAUVE, 0, 369, 42, 215, 0x0, STR_NULL}, // PATCHSEL_OPTIONSPANEL
|