From 0d12c4d83de6d832948c729ac9a4a6084e87f56e Mon Sep 17 00:00:00 2001 From: david Date: Mon, 30 Dec 2002 19:50:17 +0000 Subject: [PATCH] Removed the (apparently unused) 'factor' and 'offset' arguments from property-adjust. Modified property-adjust and property-multiply so that they always work with double values, to simplify the code. Factored out some common code. Added a 'mask' argument to the property-adjust and property-multiply commands. If mask is set to "all" (the default), then the command works as before; if mask is set to "integer", it works only to the left of the decimal point; and if mask is set to "decimal", it works only to the right of the decimal place. This functionality is useful for tuning VHF COM and NAV radios. --- src/Main/fg_commands.cxx | 222 ++++++++++++++------------------------- 1 file changed, 80 insertions(+), 142 deletions(-) diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 9c621a132..fa5228790 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -50,12 +50,10 @@ do_wrap (T * value, T min, T max) { if (min >= max) { // basic sanity check *value = min; - } else { - T range = max - min; - while (*value < min) - *value += range; - while (*value > max) - *value -= range; + } else if (*value > max) { + *value = min; + } else if (*value < min) { + *value = max; } } @@ -72,6 +70,57 @@ get_prop2 (const SGPropertyNode * arg) } +/** + * Get a double value and split it as required. + */ +static void +split_value (double full_value, const char * mask, + double * unmodifiable, double * modifiable) +{ + if (!strcmp("integer", mask)) { + *modifiable = (full_value < 0 ? ceil(full_value) : floor (full_value)); + *unmodifiable = full_value - *modifiable; + } else if (!strcmp("decimal", mask)) { + *unmodifiable = (full_value < 0 ? ceil(full_value) : floor(full_value)); + *modifiable = full_value - *unmodifiable; + } else { + if (strcmp("all", mask)) + SG_LOG(SG_GENERAL, SG_ALERT, "Bad value " << mask << " for mask;" + << " assuming 'all'"); + *unmodifiable = 0; + *modifiable = full_value; + } +} + + +/** + * Clamp or wrap a value as specified. + */ +static void +limit_value (double * value, const SGPropertyNode * arg) +{ + const SGPropertyNode * min_node = arg->getChild("min"); + const SGPropertyNode * max_node = arg->getChild("max"); + + bool wrap = arg->getBoolValue("wrap"); + + if (min_node == 0 || max_node == 0) + wrap = false; + + if (wrap) { // wrap + if (*value < min_node->getDoubleValue()) + *value = max_node->getDoubleValue(); + else if (*value > max_node->getDoubleValue()) + *value = min_node->getDoubleValue(); + } else { // clamp + if ((min_node != 0) && (*value < min_node->getDoubleValue())) + *value = min_node->getDoubleValue(); + else if ((max_node != 0) && (*value > max_node->getDoubleValue())) + *value = max_node->getDoubleValue(); + } +} + + //////////////////////////////////////////////////////////////////////// // Command implementations. @@ -373,10 +422,11 @@ do_property_assign (const SGPropertyNode * arg) * * property: the name of the property to increment or decrement. * step: the amount of the increment or decrement (default: 0). - * offset: a normalized amount to offset by (if step is not present). - * factor: the amount by which to multiply the offset (if step is not present). * min: the minimum allowed value (default: no minimum). * max: the maximum allowed value (default: no maximum). + * mask: 'integer' to apply only to the left of the decimal point, + * 'decimal' to apply only to the right of the decimal point, + * or 'all' to apply to the whole number (the default). * wrap: true if the value should be wrapped when it passes min or max; * both min and max must be present for this to work (default: * false). @@ -385,113 +435,15 @@ static bool do_property_adjust (const SGPropertyNode * arg) { SGPropertyNode * prop = get_prop(arg); - const SGPropertyNode * step = arg->getChild("step"); - const SGPropertyNode * offset = arg->getChild("offset"); - const SGPropertyNode * factor = arg->getChild("factor"); - const SGPropertyNode * min = arg->getChild("min"); - const SGPropertyNode * max = arg->getChild("max"); - bool wrap = arg->getBoolValue("wrap"); - - if (min == 0 || max == 0) - wrap = false; - - double amount = 0; - if (step == 0) - amount = offset->getDoubleValue() * factor->getDoubleValue(); - - switch (prop->getType()) { - - case SGPropertyNode::BOOL: { - bool value; - if (step != 0) - value = step->getBoolValue(); - else - value = (0.0 != amount); - if (value) - return prop->setBoolValue(!prop->getBoolValue()); - else - return true; - } - - case SGPropertyNode::INT: { - int value; - if (step != 0) - value = prop->getIntValue() + step->getIntValue(); - else - value = prop->getIntValue() + int(amount); - if (wrap) { - do_wrap(&value, min->getIntValue(), max->getIntValue()); - } else { - if (min != 0 && value < min->getIntValue()) - value = min->getIntValue(); - if (max != 0 && value > max->getIntValue()) - value = max->getIntValue(); - } - return prop->setIntValue(value); - } - - case SGPropertyNode::LONG: { - long value; - if (step != 0) - value = prop->getLongValue() + step->getLongValue(); - else - value = prop->getLongValue() + long(amount); - if (wrap) { - do_wrap(&value, min->getLongValue(), max->getLongValue()); - } else { - if (min != 0 && value < min->getLongValue()) - value = min->getLongValue(); - if (max != 0 && value > max->getLongValue()) - value = max->getLongValue(); - } - return prop->setLongValue(value); - } + double step = arg->getDoubleValue("step"); - case SGPropertyNode::FLOAT: { - float value; - if (step != 0) - value = prop->getFloatValue() + step->getFloatValue(); - else - value = prop->getFloatValue() + float(amount); - if (wrap) { - do_wrap(&value, min->getFloatValue(), max->getFloatValue()); - } else { - if (min != 0 && value < min->getFloatValue()) - value = min->getFloatValue(); - if (max != 0 && value > max->getFloatValue()) - value = max->getFloatValue(); - } - return prop->setFloatValue(value); - } + double unmodifiable, modifiable; + split_value(prop->getDoubleValue(), arg->getStringValue("mask", "all"), + &unmodifiable, &modifiable); + modifiable += step; + limit_value(&modifiable, arg); - case SGPropertyNode::DOUBLE: - case SGPropertyNode::UNSPECIFIED: - case SGPropertyNode::NONE: { - double value; - if (step != 0) - value = prop->getDoubleValue() + step->getDoubleValue(); - else - value = prop->getDoubleValue() + amount; - if (wrap) { - do_wrap(&value, min->getDoubleValue(), max->getDoubleValue()); - } else { - if (min != 0 && value < min->getDoubleValue()) - value = min->getDoubleValue(); - if (max != 0 && value > max->getDoubleValue()) - value = max->getDoubleValue(); - } - return prop->setDoubleValue(value); - } - - case SGPropertyNode::STRING: // doesn't make sense with strings - SG_LOG(SG_INPUT, SG_ALERT, "Cannot adjust a string value"); - return false; - - default: - SG_LOG(SG_INPUT, SG_ALERT, "Unknown value type"); - return false; - - } + prop->setDoubleValue(unmodifiable + modifiable); } @@ -500,42 +452,28 @@ do_property_adjust (const SGPropertyNode * arg) * * property: the name of the property to multiply. * factor: the amount by which to multiply. + * min: the minimum allowed value (default: no minimum). + * max: the maximum allowed value (default: no maximum). + * mask: 'integer' to apply only to the left of the decimal point, + * 'decimal' to apply only to the right of the decimal point, + * or 'all' to apply to the whole number (the default). + * wrap: true if the value should be wrapped when it passes min or max; + * both min and max must be present for this to work (default: + * false). */ static bool do_property_multiply (const SGPropertyNode * arg) { SGPropertyNode * prop = get_prop(arg); - const SGPropertyNode * factor = arg->getChild("factor"); - - if (factor == 0) - return true; - - switch (prop->getType()) { - - case SGPropertyNode::BOOL: - return prop->setBoolValue(prop->getBoolValue() && factor->getBoolValue()); - - case SGPropertyNode::INT: - return prop->setIntValue(int(prop->getIntValue() - * factor->getDoubleValue())); - - case SGPropertyNode::LONG: - return prop->setLongValue(long(prop->getLongValue() - * factor->getDoubleValue())); - - case SGPropertyNode::FLOAT: - return prop->setFloatValue(float(prop->getFloatValue() - * factor->getDoubleValue())); + double factor = arg->getDoubleValue("factor", 1); - case SGPropertyNode::DOUBLE: - case SGPropertyNode::UNSPECIFIED: - case SGPropertyNode::NONE: - return prop->setDoubleValue(prop->getDoubleValue() - * factor->getDoubleValue()); + double unmodifiable, modifiable; + split_value(prop->getDoubleValue(), arg->getStringValue("mask", "all"), + &unmodifiable, &modifiable); + modifiable *= factor; + limit_value(&modifiable, arg); - default: // doesn't make sense with strings - return false; - } + prop->setDoubleValue(unmodifiable + modifiable); } -- 2.39.2