mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 04:31:34 -10:00
This is a system for storing arbitrary data in the config file and then easily retrieving it later on. This has full Lua support for exposing the available options in a custom UI and changing the values of the options. This ported some of the existing command line options over to the new system which is opt-in for the moment by using a mod_table flag.
223 lines
6.7 KiB
C++
223 lines
6.7 KiB
C++
//
|
|
//
|
|
|
|
#include "option.h"
|
|
#include "enums.h"
|
|
|
|
namespace scripting {
|
|
namespace api {
|
|
|
|
ADE_OBJ(l_ValueDescription, options::ValueDescription, "ValueDescription",
|
|
"An option value that contains a displayable string and the serialized value.");
|
|
|
|
ADE_FUNC(__tostring, l_ValueDescription, nullptr, "Value display string", "string",
|
|
"The display string or nil on error")
|
|
{
|
|
options::ValueDescription* desc;
|
|
if (!ade_get_args(L, "o", l_ValueDescription.GetPtr(&desc))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "s", desc->display.c_str());
|
|
}
|
|
ADE_FUNC(__eq, l_ValueDescription, "ValueDescription other", "Compares two value descriptions", "string",
|
|
"True if equal, false otherwise")
|
|
{
|
|
options::ValueDescription* desc;
|
|
options::ValueDescription* other;
|
|
if (!ade_get_args(L, "oo", l_ValueDescription.GetPtr(&desc), l_ValueDescription.GetPtr(&other))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "b", desc->serialized == other->serialized);
|
|
}
|
|
ADE_VIRTVAR(Display, l_ValueDescription, nullptr, "Value display string", "string",
|
|
"The display string or nil on error")
|
|
{
|
|
options::ValueDescription* desc;
|
|
if (!ade_get_args(L, "o", l_ValueDescription.GetPtr(&desc))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "s", desc->display.c_str());
|
|
}
|
|
ADE_VIRTVAR(Serialized, l_ValueDescription, nullptr, "Serialized string value of the contained value", "string",
|
|
"The serialized string or nil on error")
|
|
{
|
|
options::ValueDescription* desc;
|
|
if (!ade_get_args(L, "o", l_ValueDescription.GetPtr(&desc))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "s", desc->serialized.c_str());
|
|
}
|
|
|
|
option_h::option_h(const options::OptionBase* opt) : _opt(opt) {}
|
|
bool option_h::isValid() const { return _opt != nullptr; }
|
|
const options::OptionBase* option_h::get() { return _opt; }
|
|
|
|
//**********HANDLE: Object
|
|
ADE_OBJ(l_Option, option_h, "option", "Option handle");
|
|
|
|
ADE_VIRTVAR(Title, l_Option, nullptr, "The title of this option (read-only)", "string", "The title or nil on error")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
return ade_set_args(L, "s", opt->get()->getTitle().c_str());
|
|
}
|
|
ADE_VIRTVAR(Description, l_Option, nullptr, "The description of this option (read-only)", "string",
|
|
"The description or nil on error")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
return ade_set_args(L, "s", opt->get()->getDescription().c_str());
|
|
}
|
|
ADE_VIRTVAR(Key, l_Option, nullptr, "The configuration key of this option. This will be a unique string. (read-only)",
|
|
"string", "The key or nil on error")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
return ade_set_args(L, "s", opt->get()->getConfigKey().c_str());
|
|
}
|
|
ADE_VIRTVAR(Category, l_Option, nullptr, "The category of this option. (read-only)", "string",
|
|
"The category or nil on error")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
return ade_set_args(L, "s", opt->get()->getCategory().c_str());
|
|
}
|
|
ADE_VIRTVAR(Type, l_Option, nullptr, "The type of this option. One of the OPTION_TYPE_* values. (read-only)",
|
|
"enumeration", "The enum or nil on error")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
int32_t enum_val = -1;
|
|
switch (opt->get()->getType()) {
|
|
case options::OptionType::Selection:
|
|
enum_val = LE_OPTION_TYPE_SELECTION;
|
|
break;
|
|
case options::OptionType::Range:
|
|
enum_val = LE_OPTION_TYPE_RANGE;
|
|
break;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Enum.Set(enum_h(enum_val)));
|
|
}
|
|
ADE_VIRTVAR(Value, l_Option, "ValueDescription", "The current value of this option.", "ValueDescription",
|
|
"The current value or nil on error")
|
|
{
|
|
option_h* opt;
|
|
options::ValueDescription* new_val = nullptr;
|
|
if (!ade_get_args(L, "o|o", l_Option.GetPtr(&opt), l_ValueDescription.GetPtr(&new_val))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (ADE_SETTING_VAR && new_val != nullptr) {
|
|
opt->get()->setValueDescription(*new_val);
|
|
}
|
|
return ade_set_args(L, "o", l_ValueDescription.Set(opt->get()->getCurrentValueDescription()));
|
|
}
|
|
ADE_FUNC(getValueFromRange, l_Option, "number interpolant",
|
|
"Gets a value from an option range. The specified value must be between 0 and 1.", "ValueDescription",
|
|
"The value at the specifiedposition")
|
|
{
|
|
option_h* opt;
|
|
float f;
|
|
if (!ade_get_args(L, "of", l_Option.GetPtr(&opt), &f)) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (opt->get()->getType() != options::OptionType::Range) {
|
|
LuaError(L, "This option is not a range option!");
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (f < 0.0f || f > 1.0f) {
|
|
LuaError(L, "Invalid interpolant value %f!", f);
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "o", l_ValueDescription.Set(opt->get()->getValueFromRange(f)));
|
|
}
|
|
ADE_FUNC(getInterpolantFromValue, l_Option, "ValueDescription value",
|
|
"From a value description of this option, determines the range value.", "number",
|
|
"The range value or 0 on error.")
|
|
{
|
|
option_h* opt;
|
|
options::ValueDescription* value = nullptr;
|
|
if (!ade_get_args(L, "oo", l_Option.GetPtr(&opt), l_ValueDescription.GetPtr(&value))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (opt->get()->getType() != options::OptionType::Range) {
|
|
LuaError(L, "This option is not a range option!");
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
return ade_set_args(L, "f", opt->get()->getInterpolantFromValue(*value));
|
|
}
|
|
ADE_FUNC(getValidValues, l_Option, nullptr,
|
|
"Gets the valid values of this option. The order or the returned values must be maintained in the UI. This is "
|
|
"only valid for selection or boolean options.",
|
|
"{ValueDescription...}", "A table containing the possible values or nil on error.")
|
|
{
|
|
option_h* opt;
|
|
if (!ade_get_args(L, "o", l_Option.GetPtr(&opt))) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (!opt->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
if (opt->get()->getType() == options::OptionType::Range) {
|
|
LuaError(L, "This option is not a selection or boolean option!");
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
auto values = opt->get()->getValidValues();
|
|
|
|
auto table = luacpp::LuaTable::create(L);
|
|
auto i = 1;
|
|
for (auto& value : values) {
|
|
table.addValue(i, l_ValueDescription.Set(value));
|
|
++i;
|
|
}
|
|
|
|
return ade_set_args(L, "t", &table);
|
|
}
|
|
|
|
} // namespace api
|
|
} // namespace scripting
|