mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
8 Commits
186829b99f
...
35a7770fde
Author | SHA1 | Date |
---|---|---|
|
35a7770fde | |
|
e81313e93e | |
|
de3f29d7b2 | |
|
f09fda1ff0 | |
|
0b7ecf6102 | |
|
97df27e41f | |
|
2d3fef3113 | |
|
a8aba06a07 |
|
@ -96,6 +96,7 @@ struct BaseSet {
|
|||
}
|
||||
|
||||
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
|
||||
void CopyCompatibleConfig([[maybe_unused]] const T &src) {}
|
||||
|
||||
/**
|
||||
* Get the description for the given ISO code.
|
||||
|
@ -170,9 +171,6 @@ protected:
|
|||
*/
|
||||
static const char *GetExtension();
|
||||
public:
|
||||
/** The set as saved in the config file. */
|
||||
static std::string ini_set;
|
||||
|
||||
/**
|
||||
* Determine the graphics pack that has to be used.
|
||||
* The one with the most correct files wins.
|
||||
|
@ -191,7 +189,9 @@ public:
|
|||
|
||||
static Tbase_set *GetAvailableSets();
|
||||
|
||||
static bool SetSet(const std::string &name);
|
||||
static bool SetSet(const Tbase_set *set);
|
||||
static bool SetSetByName(const std::string &name);
|
||||
static bool SetSetByShortname(uint32_t shortname);
|
||||
static void GetSetsList(std::back_insert_iterator<std::string> &output_iterator);
|
||||
static int GetNumSets();
|
||||
static int GetIndexOfUsedSet();
|
||||
|
@ -207,7 +207,6 @@ public:
|
|||
static bool HasSet(const ContentInfo *ci, bool md5sum);
|
||||
};
|
||||
|
||||
template <class Tbase_set> /* static */ std::string BaseMedia<Tbase_set>::ini_set;
|
||||
template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::used_set;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::available_sets;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplicate_sets;
|
||||
|
@ -239,12 +238,24 @@ enum BlitterType {
|
|||
BLT_32BPP, ///< Base set has both 8 bpp and 32 bpp sprites.
|
||||
};
|
||||
|
||||
struct GRFConfig;
|
||||
|
||||
/** All data of a graphics set. */
|
||||
struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
|
||||
private:
|
||||
mutable std::unique_ptr<GRFConfig> extra_cfg; ///< Parameters for extra GRF
|
||||
public:
|
||||
PaletteType palette; ///< Palette of this graphics set
|
||||
BlitterType blitter; ///< Blitter of this graphics set
|
||||
|
||||
GraphicsSet();
|
||||
~GraphicsSet();
|
||||
|
||||
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
|
||||
GRFConfig *GetExtraConfig() const { return this->extra_cfg.get(); }
|
||||
GRFConfig &GetOrCreateExtraConfig() const;
|
||||
bool IsConfigurable() const;
|
||||
void CopyCompatibleConfig(const GraphicsSet &src);
|
||||
|
||||
static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir);
|
||||
};
|
||||
|
@ -252,6 +263,15 @@ struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
|
|||
/** All data/functions related with replacing the base graphics. */
|
||||
class BaseGraphics : public BaseMedia<GraphicsSet> {
|
||||
public:
|
||||
/** Values loaded from config file. */
|
||||
struct Ini {
|
||||
std::string name;
|
||||
uint32_t shortname; ///< unique key for base set
|
||||
uint32_t extra_version; ///< version of the extra GRF
|
||||
std::vector<uint32_t> extra_params; ///< parameters for the extra GRF
|
||||
};
|
||||
static inline Ini ini_data;
|
||||
|
||||
};
|
||||
|
||||
/** All data of a sounds set. */
|
||||
|
@ -261,6 +281,9 @@ struct SoundsSet : BaseSet<SoundsSet, 1, true> {
|
|||
/** All data/functions related with replacing the base sounds */
|
||||
class BaseSounds : public BaseMedia<SoundsSet> {
|
||||
public:
|
||||
/** The set as saved in the config file. */
|
||||
static inline std::string ini_set;
|
||||
|
||||
};
|
||||
|
||||
/** Maximum number of songs in the 'class' playlists. */
|
||||
|
@ -307,6 +330,9 @@ struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
|
|||
/** All data/functions related with replacing the base music */
|
||||
class BaseMusic : public BaseMedia<MusicSet> {
|
||||
public:
|
||||
/** The set as saved in the config file. */
|
||||
static inline std::string ini_set;
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASE_MEDIA_BASE_H */
|
||||
|
|
|
@ -198,6 +198,9 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
|
|||
*prev = set;
|
||||
set->next = duplicate->next;
|
||||
|
||||
/* Keep baseset configuration, if compatible */
|
||||
set->CopyCompatibleConfig(*duplicate);
|
||||
|
||||
/* If the duplicate set is currently used (due to rescanning this can happen)
|
||||
* update the currently used set to the new one. This will 'lie' about the
|
||||
* version number until a new game is started which isn't a big problem */
|
||||
|
@ -226,25 +229,58 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set to be used.
|
||||
* @param set the set to use
|
||||
* @return true if it could be loaded
|
||||
*/
|
||||
template <class Tbase_set>
|
||||
/* static */ bool BaseMedia<Tbase_set>::SetSet(const Tbase_set *set)
|
||||
{
|
||||
if (set == nullptr) {
|
||||
if (!BaseMedia<Tbase_set>::DetermineBestSet()) return false;
|
||||
} else {
|
||||
BaseMedia<Tbase_set>::used_set = set;
|
||||
}
|
||||
CheckExternalFiles();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set to be used.
|
||||
* @param name of the set to use
|
||||
* @return true if it could be loaded
|
||||
*/
|
||||
template <class Tbase_set>
|
||||
/* static */ bool BaseMedia<Tbase_set>::SetSet(const std::string &name)
|
||||
/* static */ bool BaseMedia<Tbase_set>::SetSetByName(const std::string &name)
|
||||
{
|
||||
if (name.empty()) {
|
||||
if (!BaseMedia<Tbase_set>::DetermineBestSet()) return false;
|
||||
CheckExternalFiles();
|
||||
return true;
|
||||
return SetSet(nullptr);
|
||||
}
|
||||
|
||||
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
|
||||
if (name == s->name) {
|
||||
BaseMedia<Tbase_set>::used_set = s;
|
||||
CheckExternalFiles();
|
||||
return true;
|
||||
return SetSet(s);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set to be used.
|
||||
* @param shortname of the set to use
|
||||
* @return true if it could be loaded
|
||||
*/
|
||||
template <class Tbase_set>
|
||||
/* static */ bool BaseMedia<Tbase_set>::SetSetByShortname(uint32_t shortname)
|
||||
{
|
||||
if (shortname == 0) {
|
||||
return SetSet(nullptr);
|
||||
}
|
||||
|
||||
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
|
||||
if (shortname == s->shortname) {
|
||||
return SetSet(s);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -373,11 +409,12 @@ template <class Tbase_set>
|
|||
* @param set_type the type of the BaseSet to instantiate
|
||||
*/
|
||||
#define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \
|
||||
template std::string repl_type::ini_set; \
|
||||
template const char *repl_type::GetExtension(); \
|
||||
template bool repl_type::AddFile(const std::string &filename, size_t pathlength, const std::string &tar_filename); \
|
||||
template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \
|
||||
template bool repl_type::SetSet(const std::string &name); \
|
||||
template bool repl_type::SetSet(const set_type *set); \
|
||||
template bool repl_type::SetSetByName(const std::string &name); \
|
||||
template bool repl_type::SetSetByShortname(uint32_t shortname); \
|
||||
template void repl_type::GetSetsList(std::back_insert_iterator<std::string> &output_iterator); \
|
||||
template int repl_type::GetNumSets(); \
|
||||
template int repl_type::GetIndexOfUsedSet(); \
|
||||
|
|
|
@ -192,18 +192,8 @@ static void LoadSpriteTables()
|
|||
ClrBit(master->flags, GCF_INIT_ONLY);
|
||||
|
||||
/* Baseset extra graphics */
|
||||
GRFConfig *extra = new GRFConfig(used_set->files[GFT_EXTRA].filename.c_str());
|
||||
|
||||
/* We know the palette of the base set, so if the base NewGRF is not
|
||||
* setting one, use the palette of the base set and not the global
|
||||
* one which might be the wrong palette for this base NewGRF.
|
||||
* The value set here might be overridden via action14 later. */
|
||||
switch (used_set->palette) {
|
||||
case PAL_DOS: extra->palette |= GRFP_GRF_DOS; break;
|
||||
case PAL_WINDOWS: extra->palette |= GRFP_GRF_WINDOWS; break;
|
||||
default: break;
|
||||
}
|
||||
FillGRFDetails(extra, false, BASESET_DIR);
|
||||
GRFConfig *extra = new GRFConfig(used_set->GetOrCreateExtraConfig());
|
||||
if (extra->num_params == 0) extra->SetParameterDefaults();
|
||||
ClrBit(extra->flags, GCF_INIT_ONLY);
|
||||
|
||||
extra->next = top;
|
||||
|
@ -347,6 +337,17 @@ void GfxLoadSprites()
|
|||
UpdateCursorSize();
|
||||
}
|
||||
|
||||
GraphicsSet::GraphicsSet()
|
||||
: BaseSet<GraphicsSet, MAX_GFT, true>{}, palette{}, blitter{}
|
||||
{
|
||||
// instantiate here, because unique_ptr needs a complete type
|
||||
}
|
||||
|
||||
GraphicsSet::~GraphicsSet()
|
||||
{
|
||||
// instantiate here, because unique_ptr needs a complete type
|
||||
}
|
||||
|
||||
bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
|
||||
{
|
||||
bool ret = this->BaseSet<GraphicsSet, MAX_GFT, true>::FillSetDetails(ini, path, full_filename, false);
|
||||
|
@ -365,6 +366,46 @@ bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, co
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return configuration for the extra GRF, or lazily create it.
|
||||
* @return NewGRF configuration
|
||||
*/
|
||||
GRFConfig &GraphicsSet::GetOrCreateExtraConfig() const
|
||||
{
|
||||
if (!this->extra_cfg) {
|
||||
this->extra_cfg.reset(new GRFConfig(this->files[GFT_EXTRA].filename));
|
||||
|
||||
/* We know the palette of the base set, so if the base NewGRF is not
|
||||
* setting one, use the palette of the base set and not the global
|
||||
* one which might be the wrong palette for this base NewGRF.
|
||||
* The value set here might be overridden via action14 later. */
|
||||
switch (this->palette) {
|
||||
case PAL_DOS: this->extra_cfg->palette |= GRFP_GRF_DOS; break;
|
||||
case PAL_WINDOWS: this->extra_cfg->palette |= GRFP_GRF_WINDOWS; break;
|
||||
default: break;
|
||||
}
|
||||
FillGRFDetails(this->extra_cfg.get(), false, BASESET_DIR);
|
||||
}
|
||||
return *this->extra_cfg;
|
||||
}
|
||||
|
||||
bool GraphicsSet::IsConfigurable() const
|
||||
{
|
||||
const GRFConfig &cfg = this->GetOrCreateExtraConfig();
|
||||
/* This check is more strict than the one for NewGRF Settings.
|
||||
* There are no legacy basesets with parameters, but without Action14 */
|
||||
return !cfg.param_info.empty();
|
||||
}
|
||||
|
||||
void GraphicsSet::CopyCompatibleConfig(const GraphicsSet &src)
|
||||
{
|
||||
const GRFConfig *src_cfg = src.GetExtraConfig();
|
||||
if (src_cfg == nullptr || src_cfg->num_params == 0) return;
|
||||
GRFConfig &dest_cfg = this->GetOrCreateExtraConfig();
|
||||
if (dest_cfg.IsCompatible(src_cfg->version)) return;
|
||||
dest_cfg.CopyParams(*src_cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and check the MD5 hash of the supplied GRF.
|
||||
* @param file The file get the hash of.
|
||||
|
|
|
@ -39,7 +39,7 @@ void IniItem::SetValue(const std::string_view value)
|
|||
* @param parent the file we belong to
|
||||
* @param name the name of the group
|
||||
*/
|
||||
IniGroup::IniGroup(const std::string &name, IniGroupType type) : type(type)
|
||||
IniGroup::IniGroup(const std::string &name, IniGroupType type) : type(type), comment("\n")
|
||||
{
|
||||
this->name = StrMakeValid(name);
|
||||
}
|
||||
|
|
|
@ -3384,6 +3384,7 @@ STR_SAVE_PRESET_SAVE :{BLACK}Save
|
|||
STR_SAVE_PRESET_SAVE_TOOLTIP :{BLACK}Save the preset to the current selected name
|
||||
|
||||
# NewGRF parameters window
|
||||
STR_BASEGRF_PARAMETERS_CAPTION :{WHITE}Change base graphics parameters
|
||||
STR_NEWGRF_PARAMETERS_CAPTION :{WHITE}Change NewGRF parameters
|
||||
STR_NEWGRF_PARAMETERS_CLOSE :{BLACK}Close
|
||||
STR_NEWGRF_PARAMETERS_RESET :{BLACK}Reset
|
||||
|
|
|
@ -173,7 +173,7 @@ void MusicSystem::ChangePlaylist(PlaylistChoices pl)
|
|||
*/
|
||||
void MusicSystem::ChangeMusicSet(const std::string &set_name)
|
||||
{
|
||||
BaseMusic::SetSet(set_name);
|
||||
BaseMusic::SetSetByName(set_name);
|
||||
BaseMusic::ini_set = set_name;
|
||||
|
||||
this->BuildPlaylists();
|
||||
|
|
|
@ -66,6 +66,12 @@ GRFConfig::GRFConfig(const GRFConfig &config) :
|
|||
{
|
||||
}
|
||||
|
||||
void GRFConfig::SetParams(const std::vector<uint32_t> &pars)
|
||||
{
|
||||
this->num_params = static_cast<uint8_t>(std::min(this->param.size(), pars.size()));
|
||||
std::copy(pars.begin(), pars.begin() + this->num_params, this->param.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this NewGRF can replace an older version of the same NewGRF.
|
||||
*/
|
||||
|
|
|
@ -174,6 +174,7 @@ struct GRFConfig : ZeroedMemoryAllocator {
|
|||
struct GRFConfig *next; ///< NOSAVE: Next item in the linked list
|
||||
|
||||
bool IsCompatible(uint32_t old_version) const;
|
||||
void SetParams(const std::vector<uint32_t> &pars);
|
||||
void CopyParams(const GRFConfig &src);
|
||||
|
||||
std::optional<std::string> GetTextfile(TextfileType type) const;
|
||||
|
@ -225,6 +226,7 @@ std::string GRFBuildParamList(const GRFConfig *c);
|
|||
|
||||
/* In newgrf_gui.cpp */
|
||||
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config);
|
||||
void OpenGRFParameterWindow(bool is_baseset, GRFConfig *c, bool editable);
|
||||
|
||||
void UpdateNewGRFScanStatus(uint num, const char *name);
|
||||
void UpdateNewGRFConfigPalette(int32_t new_value = 0);
|
||||
|
|
|
@ -155,7 +155,7 @@ struct NewGRFParametersWindow : public Window {
|
|||
bool action14present; ///< True if action14 information is present.
|
||||
bool editable; ///< Allow editing parameters.
|
||||
|
||||
NewGRFParametersWindow(WindowDesc *desc, GRFConfig *c, bool editable) : Window(desc),
|
||||
NewGRFParametersWindow(WindowDesc *desc, bool is_baseset, GRFConfig *c, bool editable) : Window(desc),
|
||||
grf_config(c),
|
||||
clicked_button(UINT_MAX),
|
||||
clicked_dropdown(false),
|
||||
|
@ -166,6 +166,7 @@ struct NewGRFParametersWindow : public Window {
|
|||
this->action14present = (c->num_valid_params != c->param.size() || !c->param_info.empty());
|
||||
|
||||
this->CreateNestedTree();
|
||||
this->GetWidget<NWidgetCore>(WID_NP_CAPTION)->SetDataTip(is_baseset ? STR_BASEGRF_PARAMETERS_CAPTION : STR_NEWGRF_PARAMETERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
|
||||
this->vscroll = this->GetScrollbar(WID_NP_SCROLLBAR);
|
||||
this->GetWidget<NWidgetStacked>(WID_NP_SHOW_NUMPAR)->SetDisplayedPlane(this->action14present ? SZSP_HORIZONTAL : 0);
|
||||
this->GetWidget<NWidgetStacked>(WID_NP_SHOW_DESCRIPTION)->SetDisplayedPlane(this->action14present ? 0 : SZSP_HORIZONTAL);
|
||||
|
@ -509,7 +510,7 @@ GRFParameterInfo NewGRFParametersWindow::dummy_parameter_info(0);
|
|||
static const NWidgetPart _nested_newgrf_parameter_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_NEWGRF_PARAMETERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_NP_CAPTION),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NP_SHOW_NUMPAR),
|
||||
|
@ -546,10 +547,10 @@ static WindowDesc _newgrf_parameters_desc(
|
|||
std::begin(_nested_newgrf_parameter_widgets), std::end(_nested_newgrf_parameter_widgets)
|
||||
);
|
||||
|
||||
static void OpenGRFParameterWindow(GRFConfig *c, bool editable)
|
||||
void OpenGRFParameterWindow(bool is_baseset, GRFConfig *c, bool editable)
|
||||
{
|
||||
CloseWindowByClass(WC_GRF_PARAMETERS);
|
||||
new NewGRFParametersWindow(&_newgrf_parameters_desc, c, editable);
|
||||
new NewGRFParametersWindow(&_newgrf_parameters_desc, is_baseset, c, editable);
|
||||
}
|
||||
|
||||
/** Window for displaying the textfile of a NewGRF. */
|
||||
|
@ -1133,7 +1134,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
|
|||
case WID_NS_SET_PARAMETERS: { // Edit parameters
|
||||
if (this->active_sel == nullptr || !this->show_params || this->active_sel->num_valid_params == 0) break;
|
||||
|
||||
OpenGRFParameterWindow(this->active_sel, this->editable);
|
||||
OpenGRFParameterWindow(false, this->active_sel, this->editable);
|
||||
this->InvalidateData(GOID_NEWGRF_CHANGES_MADE);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -700,15 +700,31 @@ int openttd_main(int argc, char *argv[])
|
|||
InitWindowSystem();
|
||||
|
||||
BaseGraphics::FindSets();
|
||||
if (graphics_set.empty() && !BaseGraphics::ini_set.empty()) graphics_set = BaseGraphics::ini_set;
|
||||
if (!BaseGraphics::SetSet(graphics_set)) {
|
||||
if (!graphics_set.empty()) {
|
||||
BaseGraphics::SetSet({});
|
||||
|
||||
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
|
||||
msg.SetDParamStr(0, graphics_set);
|
||||
ScheduleErrorMessage(msg);
|
||||
bool valid_graphics_set;
|
||||
if (!graphics_set.empty()) {
|
||||
valid_graphics_set = BaseGraphics::SetSetByName(graphics_set);
|
||||
} else if (BaseGraphics::ini_data.shortname != 0) {
|
||||
graphics_set = BaseGraphics::ini_data.name;
|
||||
valid_graphics_set = BaseGraphics::SetSetByShortname(BaseGraphics::ini_data.shortname);
|
||||
if (valid_graphics_set && !BaseGraphics::ini_data.extra_params.empty()) {
|
||||
GRFConfig &extra_cfg = BaseGraphics::GetUsedSet()->GetOrCreateExtraConfig();
|
||||
if (extra_cfg.IsCompatible(BaseGraphics::ini_data.extra_version)) {
|
||||
extra_cfg.SetParams(BaseGraphics::ini_data.extra_params);
|
||||
}
|
||||
}
|
||||
} else if (!BaseGraphics::ini_data.name.empty()) {
|
||||
graphics_set = BaseGraphics::ini_data.name;
|
||||
valid_graphics_set = BaseGraphics::SetSetByName(BaseGraphics::ini_data.name);
|
||||
} else {
|
||||
valid_graphics_set = true;
|
||||
BaseGraphics::SetSet(nullptr); // ignore error, continue to bootstrap GUI
|
||||
}
|
||||
if (!valid_graphics_set) {
|
||||
BaseGraphics::SetSet(nullptr);
|
||||
|
||||
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
|
||||
msg.SetDParamStr(0, graphics_set);
|
||||
ScheduleErrorMessage(msg);
|
||||
}
|
||||
|
||||
/* Initialize game palette */
|
||||
|
@ -762,7 +778,7 @@ int openttd_main(int argc, char *argv[])
|
|||
|
||||
BaseSounds::FindSets();
|
||||
if (sounds_set.empty() && !BaseSounds::ini_set.empty()) sounds_set = BaseSounds::ini_set;
|
||||
if (!BaseSounds::SetSet(sounds_set)) {
|
||||
if (!BaseSounds::SetSetByName(sounds_set)) {
|
||||
if (sounds_set.empty() || !BaseSounds::SetSet({})) {
|
||||
UserError("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 1.4 of README.md.");
|
||||
} else {
|
||||
|
@ -774,7 +790,7 @@ int openttd_main(int argc, char *argv[])
|
|||
|
||||
BaseMusic::FindSets();
|
||||
if (music_set.empty() && !BaseMusic::ini_set.empty()) music_set = BaseMusic::ini_set;
|
||||
if (!BaseMusic::SetSet(music_set)) {
|
||||
if (!BaseMusic::SetSetByName(music_set)) {
|
||||
if (music_set.empty() || !BaseMusic::SetSet({})) {
|
||||
UserError("Failed to find a music set. Please acquire a music set for OpenTTD. See section 1.4 of README.md.");
|
||||
} else {
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ai/ai_config.hpp"
|
||||
#include "game/game_config.hpp"
|
||||
#include "newgrf_config.h"
|
||||
#include "base_media_base.h"
|
||||
#include "fios.h"
|
||||
#include "fileio_func.h"
|
||||
#include "settings_cmd.h"
|
||||
|
@ -981,6 +982,40 @@ static bool DecodeHexText(const char *pos, uint8_t *dest, size_t dest_size)
|
|||
return *pos == '|';
|
||||
}
|
||||
|
||||
/**
|
||||
* Load BaseGraphics set selection and configuration.
|
||||
*/
|
||||
static void GraphicsSetLoadConfig(IniFile &ini)
|
||||
{
|
||||
if (const IniGroup *group = ini.GetGroup("misc"); group != nullptr) {
|
||||
/* Load old setting first. */
|
||||
if (const IniItem *item = group->GetItem("graphicsset"); item != nullptr && item->value) BaseGraphics::ini_data.name = *item->value;
|
||||
}
|
||||
|
||||
if (const IniGroup *group = ini.GetGroup("graphicsset"); group != nullptr) {
|
||||
/* Load new settings. */
|
||||
if (const IniItem *item = group->GetItem("name"); item != nullptr && item->value) BaseGraphics::ini_data.name = *item->value;
|
||||
|
||||
if (const IniItem *item = group->GetItem("shortname"); item != nullptr && item->value && item->value->size() == 8) {
|
||||
BaseGraphics::ini_data.shortname = BSWAP32(std::strtoul(item->value->c_str(), nullptr, 16));
|
||||
}
|
||||
|
||||
if (const IniItem *item = group->GetItem("extra_version"); item != nullptr && item->value) BaseGraphics::ini_data.extra_version = std::strtoul(item->value->c_str(), nullptr, 10);
|
||||
|
||||
if (const IniItem *item = group->GetItem("extra_params"); item != nullptr && item->value) {
|
||||
auto &extra_params = BaseGraphics::ini_data.extra_params;
|
||||
extra_params.resize(lengthof(GRFConfig::param));
|
||||
int count = ParseIntList(item->value->c_str(), &extra_params.front(), extra_params.size());
|
||||
if (count < 0) {
|
||||
SetDParamStr(0, BaseGraphics::ini_data.name);
|
||||
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
|
||||
count = 0;
|
||||
}
|
||||
extra_params.resize(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a GRF configuration
|
||||
* @param ini The configuration to read from.
|
||||
|
@ -1153,6 +1188,27 @@ static void SaveVersionInConfig(IniFile &ini)
|
|||
group.GetOrCreateItem("ini_version").SetValue(std::to_string(INIFILE_VERSION));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save BaseGraphics set selection and configuration.
|
||||
*/
|
||||
static void GraphicsSetSaveConfig(IniFile &ini)
|
||||
{
|
||||
const GraphicsSet *used_set = BaseGraphics::GetUsedSet();
|
||||
if (used_set == nullptr) return;
|
||||
|
||||
IniGroup &group = ini.GetOrCreateGroup("graphicsset");
|
||||
group.Clear();
|
||||
|
||||
group.GetOrCreateItem("name").SetValue(used_set->name);
|
||||
group.GetOrCreateItem("shortname").SetValue(fmt::format("{:08X}", BSWAP32(used_set->shortname)));
|
||||
|
||||
const GRFConfig *extra_cfg = used_set->GetExtraConfig();
|
||||
if (extra_cfg != nullptr && extra_cfg->num_params > 0) {
|
||||
group.GetOrCreateItem("extra_version").SetValue(fmt::format("{}", extra_cfg->version));
|
||||
group.GetOrCreateItem("extra_params").SetValue(GRFBuildParamList(extra_cfg));
|
||||
}
|
||||
}
|
||||
|
||||
/* Save a GRF configuration to the given group name */
|
||||
static void GRFSaveConfig(IniFile &ini, const char *grpname, const GRFConfig *list)
|
||||
{
|
||||
|
@ -1285,6 +1341,10 @@ void LoadFromConfig(bool startup)
|
|||
|
||||
IniFileVersion generic_version = LoadVersionFromConfig(generic_ini);
|
||||
|
||||
if (startup) {
|
||||
GraphicsSetLoadConfig(generic_ini);
|
||||
}
|
||||
|
||||
/* Before the split of private/secrets, we have to look in the generic for these settings. */
|
||||
if (generic_version < IFV_PRIVATE_SECRETS) {
|
||||
HandleSettingDescs(generic_ini, generic_ini, generic_ini, IniLoadSettings, IniLoadSettingList, startup);
|
||||
|
@ -1416,6 +1476,7 @@ void SaveToConfig()
|
|||
}
|
||||
|
||||
HandleSettingDescs(generic_ini, private_ini, secrets_ini, IniSaveSettings, IniSaveSettingList);
|
||||
GraphicsSetSaveConfig(generic_ini);
|
||||
GRFSaveConfig(generic_ini, "newgrf", _grfconfig_newgame);
|
||||
GRFSaveConfig(generic_ini, "newgrf-static", _grfconfig_static);
|
||||
AISaveConfig(generic_ini, "ai_players");
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "music/music_driver.hpp"
|
||||
#include "gui.h"
|
||||
#include "mixer.h"
|
||||
#include "newgrf_config.h"
|
||||
#include "network/core/config.h"
|
||||
#include "network/network_gui.h"
|
||||
#include "network/network_survey.h"
|
||||
|
@ -601,6 +602,16 @@ struct GameOptionsWindow : Window {
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_GO_BASE_GRF_PARAMETERS: {
|
||||
auto *used_set = BaseGraphics::GetUsedSet();
|
||||
if (used_set == nullptr || !used_set->IsConfigurable()) break;
|
||||
GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
|
||||
if (extra_cfg.num_params == 0) extra_cfg.SetParameterDefaults();
|
||||
OpenGRFParameterWindow(true, &extra_cfg, _game_mode == GM_MENU);
|
||||
if (_game_mode == GM_MENU) this->reload = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_GO_BASE_SFX_VOLUME:
|
||||
case WID_GO_BASE_MUSIC_VOLUME: {
|
||||
byte &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
|
||||
|
@ -649,25 +660,6 @@ struct GameOptionsWindow : Window {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base media set.
|
||||
* @param index the index of the media set
|
||||
* @tparam T class of media set
|
||||
*/
|
||||
template <class T>
|
||||
void SetMediaSet(int index)
|
||||
{
|
||||
if (_game_mode == GM_MENU) {
|
||||
auto name = T::GetSet(index)->name;
|
||||
|
||||
T::ini_set = name;
|
||||
|
||||
T::SetSet(name);
|
||||
this->reload = true;
|
||||
this->InvalidateData();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDropdownSelect(int widget, int index) override
|
||||
{
|
||||
switch (widget) {
|
||||
|
@ -710,11 +702,23 @@ struct GameOptionsWindow : Window {
|
|||
}
|
||||
|
||||
case WID_GO_BASE_GRF_DROPDOWN:
|
||||
this->SetMediaSet<BaseGraphics>(index);
|
||||
if (_game_mode == GM_MENU) {
|
||||
CloseWindowByClass(WC_GRF_PARAMETERS);
|
||||
auto* set = BaseGraphics::GetSet(index);
|
||||
BaseGraphics::SetSet(set);
|
||||
this->reload = true;
|
||||
this->InvalidateData();
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_GO_BASE_SFX_DROPDOWN:
|
||||
this->SetMediaSet<BaseSounds>(index);
|
||||
if (_game_mode == GM_MENU) {
|
||||
auto* set = BaseSounds::GetSet(index);
|
||||
BaseSounds::ini_set = set->name;
|
||||
BaseSounds::SetSet(set);
|
||||
this->reload = true;
|
||||
this->InvalidateData();
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_GO_BASE_MUSIC_DROPDOWN:
|
||||
|
@ -750,6 +754,8 @@ struct GameOptionsWindow : Window {
|
|||
bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
|
||||
this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
|
||||
|
||||
this->SetWidgetDisabledState(WID_GO_BASE_GRF_PARAMETERS, BaseGraphics::GetUsedSet() == nullptr || !BaseGraphics::GetUsedSet()->IsConfigurable());
|
||||
|
||||
for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
|
||||
this->SetWidgetDisabledState(WID_GO_BASE_GRF_TEXTFILE + tft, BaseGraphics::GetUsedSet() == nullptr || !BaseGraphics::GetUsedSet()->GetTextfile(tft).has_value());
|
||||
this->SetWidgetDisabledState(WID_GO_BASE_SFX_TEXTFILE + tft, BaseSounds::GetUsedSet() == nullptr || !BaseSounds::GetUsedSet()->GetTextfile(tft).has_value());
|
||||
|
@ -861,6 +867,7 @@ static const NWidgetPart _nested_game_options_widgets[] = {
|
|||
NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(100, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_PARAMETERS), SetDataTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS, STR_NULL),
|
||||
EndContainer(),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(200, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
||||
|
|
|
@ -1186,7 +1186,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
|
|||
this->legend_width = (FONT_HEIGHT_SMALL - ScaleGUITrad(1)) * 8 / 5;
|
||||
|
||||
/* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
|
||||
this->column_width = min_width + this->legend_width + WidgetDimensions::scaled.framerect.Horizontal();
|
||||
this->column_width = min_width + WidgetDimensions::scaled.hsep_normal + this->legend_width + WidgetDimensions::scaled.framerect.Horizontal();
|
||||
}
|
||||
|
||||
/* virtual */ void SmallMapWindow::OnPaint()
|
||||
|
@ -1222,7 +1222,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
|
|||
bool rtl = _current_text_dir == TD_RTL;
|
||||
uint i = 0; // Row counter for industry legend.
|
||||
uint row_height = FONT_HEIGHT_SMALL;
|
||||
int padding = WidgetDimensions::scaled.hsep_normal;
|
||||
int padding = ScaleGUITrad(1);
|
||||
|
||||
Rect origin = r.WithWidth(this->column_width, rtl).Shrink(WidgetDimensions::scaled.framerect).WithHeight(row_height);
|
||||
Rect text = origin.Indent(this->legend_width + WidgetDimensions::scaled.hsep_normal, rtl);
|
||||
|
|
|
@ -94,13 +94,6 @@ max = 2
|
|||
full = _support8bppmodes
|
||||
cat = SC_BASIC
|
||||
|
||||
[SDTG_SSTR]
|
||||
name = ""graphicsset""
|
||||
type = SLE_STRQ
|
||||
var = BaseGraphics::ini_set
|
||||
def = nullptr
|
||||
cat = SC_BASIC
|
||||
|
||||
[SDTG_SSTR]
|
||||
name = ""soundsset""
|
||||
type = SLE_STRQ
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
/** Widgets of the #NewGRFParametersWindow class. */
|
||||
enum NewGRFParametersWidgets {
|
||||
WID_NP_CAPTION, ///< Caption of the window.
|
||||
WID_NP_SHOW_NUMPAR, ///< #NWID_SELECTION to optionally display #WID_NP_NUMPAR.
|
||||
WID_NP_NUMPAR_DEC, ///< Button to decrease number of parameters.
|
||||
WID_NP_NUMPAR_INC, ///< Button to increase number of parameters.
|
||||
|
|
|
@ -26,6 +26,7 @@ enum GameOptionsWidgets {
|
|||
WID_GO_GUI_SCALE_AUTO, ///< Autodetect GUI scale button.
|
||||
WID_GO_GUI_SCALE_BEVEL_BUTTON, ///< Toggle for chunky bevels.
|
||||
WID_GO_BASE_GRF_DROPDOWN, ///< Use to select a base GRF.
|
||||
WID_GO_BASE_GRF_PARAMETERS, ///< Base GRF parameters.
|
||||
WID_GO_BASE_GRF_STATUS, ///< Info about missing files etc.
|
||||
WID_GO_BASE_GRF_TEXTFILE, ///< Open base GRF readme, changelog (+1) or license (+2).
|
||||
WID_GO_BASE_GRF_DESCRIPTION = WID_GO_BASE_GRF_TEXTFILE + TFT_CONTENT_END, ///< Description of selected base GRF.
|
||||
|
|
Loading…
Reference in New Issue