Merge branch 'pack-default-settings' into 'master'

Pack default settings

Closes #5925

See merge request OpenMW/openmw!822
libera
psi29a 4 years ago
commit 4bc7012104

@ -438,8 +438,8 @@ endif (APPLE)
# Other files
configure_resource_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}" "settings-default.cfg")
pack_resource_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}" "defaults.bin")
configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
"${OpenMW_BINARY_DIR}" "openmw.appdata.xml")
@ -516,6 +516,7 @@ endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clan
add_subdirectory (extern/osg-ffmpeg-videoplayer)
add_subdirectory (extern/oics)
add_subdirectory (extern/Base64)
if (BUILD_OPENCS)
add_subdirectory (extern/osgQt)
endif()
@ -805,7 +806,7 @@ elseif(NOT APPLE)
INSTALL(FILES "${OpenMW_SOURCE_DIR}/README.md" DESTINATION "." RENAME "README.txt")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/LICENSE" DESTINATION "." RENAME "LICENSE.txt")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/mygui/DejaVuFontLicense.txt" DESTINATION ".")
INSTALL(FILES "${INSTALL_SOURCE}/settings-default.cfg" DESTINATION ".")
INSTALL(FILES "${INSTALL_SOURCE}/defaults.bin" DESTINATION ".")
INSTALL(FILES "${INSTALL_SOURCE}/gamecontrollerdb.txt" DESTINATION ".")
INSTALL(DIRECTORY "${INSTALL_SOURCE}/resources" DESTINATION ".")
@ -913,7 +914,7 @@ elseif(NOT APPLE)
ENDIF(BUILD_OPENCS)
# Install global configuration files
INSTALL(FILES "${INSTALL_SOURCE}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${INSTALL_SOURCE}/defaults.bin" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${INSTALL_SOURCE}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${INSTALL_SOURCE}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${INSTALL_SOURCE}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")

@ -424,11 +424,11 @@ bool Launcher::MainDialog::setupGraphicsSettings()
mEngineSettings.clear();
// Create the settings manager and load default settings file
const std::string localDefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string();
const std::string globalDefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string();
const std::string localDefault = (mCfgMgr.getLocalPath() / "defaults.bin").string();
const std::string globalDefault = (mCfgMgr.getGlobalPath() / "defaults.bin").string();
std::string defaultPath;
// Prefer the settings-default.cfg in the current directory.
// Prefer the defaults.bin in the current directory.
if (boost::filesystem::exists(localDefault))
defaultPath = localDefault;
else if (boost::filesystem::exists(globalDefault))
@ -436,7 +436,7 @@ bool Launcher::MainDialog::setupGraphicsSettings()
// Something's very wrong if we can't find the file at all.
else {
cfgError(tr("Error reading OpenMW configuration file"),
tr("<br><b>Could not find settings-default.cfg</b><br><br> \
tr("<br><b>Could not find defaults.bin</b><br><br> \
The problem may be due to an incomplete installation of OpenMW.<br> \
Reinstalling OpenMW may resolve the problem."));
return false;
@ -447,7 +447,7 @@ bool Launcher::MainDialog::setupGraphicsSettings()
mEngineSettings.loadDefault(defaultPath);
}
catch (std::exception& e) {
std::string msg = std::string("<br><b>Error reading settings-default.cfg</b><br><br>") + e.what();
std::string msg = std::string("<br><b>Error reading defaults.bin</b><br><br>") + e.what();
cfgError(tr("Error reading OpenMW configuration file"), tr(msg.c_str()));
return false;
}

@ -198,7 +198,7 @@ if(APPLE)
add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files)
configure_file("${OpenMW_BINARY_DIR}/settings-default.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/defaults.bin" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)

@ -478,8 +478,8 @@ void OMW::Engine::setSkipMenu (bool skipMenu, bool newGame)
std::string OMW::Engine::loadSettings (Settings::Manager & settings)
{
// Create the settings manager and load default settings file
const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string();
const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string();
const std::string localdefault = (mCfgMgr.getLocalPath() / "defaults.bin").string();
const std::string globaldefault = (mCfgMgr.getGlobalPath() / "defaults.bin").string();
// prefer local
if (boost::filesystem::exists(localdefault))
@ -487,7 +487,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
else if (boost::filesystem::exists(globaldefault))
settings.loadDefault(globaldefault);
else
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
throw std::runtime_error ("No default settings file found! Make sure the file \"defaults.bin\" was properly installed.");
// load user settings if they exist
const std::string settingspath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string();

@ -199,6 +199,18 @@ macro (configure_resource_file source_path destination_dir_base dest_path_relati
endif (multi_config)
endmacro (configure_resource_file)
macro (pack_resource_file source_path destination_dir_base dest_path_relative)
get_generator_is_multi_config(multi_config)
if (multi_config)
foreach(cfgtype ${CMAKE_CONFIGURATION_TYPES})
execute_process(COMMAND ${CMAKE_COMMAND} "-DINPUT_FILE=${source_path}" "-DOUTPUT_FILE=${destination_dir_base}/${cfgtype}/${dest_path_relative}" -P "${CMAKE_SOURCE_DIR}/cmake/base64.cmake")
endforeach(cfgtype)
else (multi_config)
execute_process(COMMAND ${CMAKE_COMMAND} "-DINPUT_FILE=${source_path}" "-DOUTPUT_FILE=${destination_dir_base}/${dest_path_relative}" -P "${CMAKE_SOURCE_DIR}/cmake/base64.cmake")
endif (multi_config)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${source_path}")
endmacro (pack_resource_file)
macro (copy_all_resource_files source_dir destination_dir_base destination_dir_relative files)
foreach (f ${files})
get_filename_component(filename ${f} NAME)

@ -0,0 +1,74 @@
# math(EXPR "...") can't parse hex until 3.13
cmake_minimum_required(VERSION 3.13)
if (NOT DEFINED INPUT_FILE)
message(STATUS "Usage: cmake -DINPUT_FILE=\"infile.ext\" -DOUTPUT_FILE=\"out.txt\" -P base64.cmake")
message(FATAL_ERROR "INPUT_FILE not specified")
endif()
if (NOT DEFINED OUTPUT_FILE)
message(STATUS "Usage: cmake -DINPUT_FILE=\"infile.ext\" -DOUTPUT_FILE=\"out.txt\" -P base64.cmake")
message(FATAL_ERROR "OUTPUT_FILE not specified")
endif()
if (NOT EXISTS ${INPUT_FILE})
message(FATAL_ERROR "INPUT_FILE ${INPUT_FILE} does not exist")
endif()
set(lut "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
file(READ "${INPUT_FILE}" hexContent HEX)
set(base64Content "")
while(TRUE)
string(LENGTH "${hexContent}" tailLength)
if (tailLength LESS 1)
break()
endif()
string(SUBSTRING "${hexContent}" 0 6 head)
# base64 works on three-byte chunks. Pad.
string(LENGTH "${head}" headLength)
if (headLength LESS 6)
set(hexContent "")
math(EXPR padSize "6 - ${headLength}")
set(pad "")
foreach(i RANGE 1 ${padSize})
string(APPEND pad "0")
endforeach()
string(APPEND head "${pad}")
else()
string(SUBSTRING "${hexContent}" 6 -1 hexContent)
set(padSize 0)
endif()
# get six-bit slices
math(EXPR first "0x${head} >> 18")
math(EXPR second "(0x${head} & 0x3F000) >> 12")
math(EXPR third "(0x${head} & 0xFC0) >> 6")
math(EXPR fourth "0x${head} & 0x3F")
# first two characters are always needed to represent the first byte
string(SUBSTRING "${lut}" ${first} 1 char)
string(APPEND base64Content "${char}")
string(SUBSTRING "${lut}" ${second} 1 char)
string(APPEND base64Content "${char}")
# if there's no second byte, pad with =
if (NOT padSize EQUAL 4)
string(SUBSTRING "${lut}" ${third} 1 char)
string(APPEND base64Content "${char}")
else()
string(APPEND base64Content "=")
endif()
# if there's no third byte, pad with =
if (padSize EQUAL 0)
string(SUBSTRING "${lut}" ${fourth} 1 char)
string(APPEND base64Content "${char}")
else()
string(APPEND base64Content "=")
endif()
endwhile()
file(WRITE "${OUTPUT_FILE}" "${base64Content}")

@ -251,6 +251,8 @@ target_link_libraries(components
RecastNavigation::DebugUtils
RecastNavigation::Detour
RecastNavigation::Recast
Base64
)
target_link_libraries(components ${BULLET_LIBRARIES})

@ -7,19 +7,36 @@
#include <boost/filesystem/fstream.hpp>
void Settings::SettingsFileParser::loadSettingsFile(const std::string& file, CategorySettingValueMap& settings)
#include <Base64.h>
void Settings::SettingsFileParser::loadSettingsFile(const std::string& file, CategorySettingValueMap& settings, bool base64Encoded)
{
mFile = file;
boost::filesystem::ifstream stream;
stream.open(boost::filesystem::path(file));
boost::filesystem::ifstream fstream;
fstream.open(boost::filesystem::path(file));
auto stream = std::ref<std::istream>(fstream);
std::istringstream decodedStream;
if (base64Encoded)
{
std::string base64String(std::istreambuf_iterator<char>(fstream), {});
std::string decodedString;
auto result = Base64::Base64::Decode(base64String, decodedString);
if (!result.empty())
fail("Could not decode Base64 file: " + result);
// Move won't do anything until C++20, but won't hurt to do it anyway.
decodedStream.str(std::move(decodedString));
stream = std::ref<std::istream>(decodedStream);
}
Log(Debug::Info) << "Loading settings file: " << file;
std::string currentCategory;
mLine = 0;
while (!stream.eof() && !stream.fail())
while (!stream.get().eof() && !stream.get().fail())
{
++mLine;
std::string line;
std::getline( stream, line );
std::getline( stream.get(), line );
size_t i = 0;
if (!skipWhiteSpace(i, line))
@ -255,7 +272,7 @@ void Settings::SettingsFileParser::saveSettingsFile(const std::string& file, con
ostream << "# This is the OpenMW user 'settings.cfg' file. This file only contains" << std::endl;
ostream << "# explicitly changed settings. If you would like to revert a setting" << std::endl;
ostream << "# to its default, simply remove it from this file. For available" << std::endl;
ostream << "# settings, see the file 'settings-default.cfg' or the documentation at:" << std::endl;
ostream << "# settings, see the file 'files/settings-default.cfg' in our source repo or the documentation at:" << std::endl;
ostream << "#" << std::endl;
ostream << "# https://openmw.readthedocs.io/en/master/reference/modding/settings/index.html" << std::endl;
}

@ -10,7 +10,7 @@ namespace Settings
class SettingsFileParser
{
public:
void loadSettingsFile(const std::string& file, CategorySettingValueMap& settings);
void loadSettingsFile(const std::string& file, CategorySettingValueMap& settings, bool base64encoded = false);
void saveSettingsFile(const std::string& file, const CategorySettingValueMap& settings);

@ -22,7 +22,7 @@ void Manager::clear()
void Manager::loadDefault(const std::string &file)
{
SettingsFileParser parser;
parser.loadSettingsFile(file, mDefaultSettings);
parser.loadSettingsFile(file, mDefaultSettings, true);
}
void Manager::loadUser(const std::string &file)
@ -49,7 +49,7 @@ std::string Manager::getString(const std::string &setting, const std::string &ca
return it->second;
throw std::runtime_error(std::string("Trying to retrieve a non-existing setting: ") + setting
+ ".\nMake sure the settings-default.cfg file was properly installed.");
+ ".\nMake sure the defaults.bin file was properly installed.");
}
float Manager::getFloat (const std::string& setting, const std::string& category)

@ -8,6 +8,14 @@ If you are familiar with ``.ini`` tweaks in Morrowind or the other games, this w
All settings described in this section are changed in ``settings.cfg``, located in your OpenMW user directory.
See :doc:`../paths` for this location.
When creating a new game based on the OpenMW engine, it may be desirable to change the default settings - the defaults are chosen for compatibility with Morrowind.
This can be done by editing ``defaults.bin`` in the OpenMW installation directory without rebuilding OpenMW itself.
If you're using a custom fork of OpenMW, ``files/settings-default.cfg`` in the source repository should be edited instead.
To edit ``defaults.bin``, base64 decode it, make any changes, and then base64 encode it again.
If you feel a need to edit the default settings for any other reason than when creating a new OpenMW-based game, you should not.
We may be able to accommodate your desired workflow some other way if you make a feature request.
Changing Settings
#################
@ -25,8 +33,10 @@ Changing Settings
Then to the line above, type ``[GUI]``, as the tooltip delay setting comes from the "GUI Settings" section.
Although this guide attempts to be comprehensive and up to date,
you will always be able to find the full list of settings available and their default values in ``settings-default.cfg``
in your main OpenMW installation directory.
you will always be able to find the full list of settings available and their default values in ``settings-default.cfg``,
available in the ``files`` directory of our source repo, or by base64 decoding ``defaults.bin`` in your main OpenMW installation directory.
This has changed compared to previous versions of OpenMW as more users were confused by the existence of a file they weren't supposed to edit
than were helped by the existence of a file listing settings they could edit in a different file.
The ranges included with each setting are the physically possible ranges, not recommendations.
.. warning::

@ -0,0 +1,124 @@
#ifndef _MACARON_BASE64_H_
#define _MACARON_BASE64_H_
/**
* The MIT License (MIT)
* Copyright (c) 2016 tomykaira
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string>
namespace Base64 {
class Base64 {
public:
static std::string Encode(const std::string data) {
static constexpr char sEncodingTable[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
size_t in_len = data.size();
size_t out_len = 4 * ((in_len + 2) / 3);
std::string ret(out_len, '\0');
size_t i;
char *p = ret.data();
for (i = 0; i < in_len - 2; i += 3) {
*p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
*p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)];
*p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int) (data[i + 2] & 0xC0) >> 6)];
*p++ = sEncodingTable[data[i + 2] & 0x3F];
}
if (i < in_len) {
*p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
if (i == (in_len - 1)) {
*p++ = sEncodingTable[((data[i] & 0x3) << 4)];
*p++ = '=';
}
else {
*p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)];
*p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
return ret;
}
static std::string Decode(const std::string& input, std::string& out) {
static constexpr unsigned char kDecodingTable[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
size_t in_len = input.size();
if (in_len % 4 != 0) return "Input data size is not a multiple of 4";
size_t out_len = in_len / 4 * 3;
if (input[in_len - 1] == '=') out_len--;
if (input[in_len - 2] == '=') out_len--;
out.resize(out_len);
for (size_t i = 0, j = 0; i < in_len;) {
uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF;
if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF;
if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF;
}
return "";
}
};
}
#endif /* _MACARON_BASE64_H_ */

@ -0,0 +1,2 @@
add_library(Base64 INTERFACE)
target_include_directories(Base64 INTERFACE .)

@ -1,6 +1,7 @@
# WARNING: If this file is named settings-default.cfg, then editing
# this file might have no effect, as these settings may be overwritten
# by your user settings.cfg file (see documentation for its location).
# WARNING: If this file is named settings-default.cfg or was generated
# from defaults.bin, then editing this file might have no effect, as
# these settings may be overwritten by your user settings.cfg file
# (see documentation for its location).
#
# This file provides minimal documentation for each setting, and
# ranges of recommended values. For detailed explanations of the

Loading…
Cancel
Save