コード例 #1
0
ファイル: PartModuleFields.cs プロジェクト: vincentBenet/KOS
        /// <summary>
        /// Return true if the value given is allowed for the field given.  This uses the hints from the GUI
        /// system to decide what is and isn't allowed.  (For example if a GUI slider goes from 10 to 20 at
        /// increments of 2, then a value of 17 is not something you could achieve in the GUI, being only able
        /// to go from 16 to 18 skipping over 17, and therefore this routine would return false for trying to
        /// set it to 17).
        /// <br/><br/>
        /// Note that the value passed in may be altered (which is why it's ref) when it's not
        /// exactly legal, but it's CLOSE ENOUGH to be coerced into a legal value.  For example,
        /// you set a slider to 10.45 and the slider only allows values on the 0.5 marks like 10, 10.5, 11. etc.
        /// Rather than deny the attempt, the value will be nudged to the nearest legal value.
        /// </summary>
        /// <param name="field">Which KSPField is being checked?</param>
        /// <param name="newVal">What is the value it's being set to?  It is possible to
        ///    alter the value to an acceptable replacement which is why it passes by ref</param>
        /// <param name="except">An exception you can choose to throw if you want, or null if the value is legal.</param>
        /// <returns>Is it legal?</returns>
        private bool IsLegalValue(BaseField field, ref Structure newVal, out KOSException except)
        {
            except = null;
            bool isLegal = true;

            Type   fType        = field.FieldInfo.FieldType;
            object convertedVal = newVal;

            // Using TryGetFieldUIControl() to obtain the control that goes with this
            // field is from advice from TriggerAU, of SQUAD, who gave that advice in
            // a forum post when I described the problems we were having with the servo
            // parts in Breaking Ground DLC.  (There is some kind of work being done here
            // that seems to allow one field's ranges to override another's as the servo
            // parts need to do.  This is work which doesn't seem to happen if you look at
            // the KSPField's control ranges directly):
            UI_Control control;

            if (!partModule.Fields.TryGetFieldUIControl(field.name, out control))
            {
                throw new KOSInvalidFieldValueException("Field appears to have no UI control attached so kOS refuses to let a script change it.");
            }
            if (!control.controlEnabled)
            {
                except = new KOSInvalidFieldValueException("Field is read-only");
                return(false);
            }
            if (!newVal.GetType().IsSubclassOf(fType))
            {
                try
                {
                    convertedVal = Convert.ChangeType(newVal, fType);
                }
                catch (InvalidCastException)
                {
                    except = new KOSCastException(newVal.GetType(), fType);
                    return(false);
                }
                catch (FormatException)
                {
                    except = new KOSCastException(newVal.GetType(), fType);
                    return(false);
                }
            }

            // Some of these are subclasses of each other, so don't change this to an if/else.
            // It's a series of if's on purpose so it checks all classes the control is derived from.
            if (control is UI_Toggle)
            {
                // Seems there's nothing to check here, but maybe later there will be?
            }
            if (control is UI_Label)
            {
                except  = new KOSInvalidFieldValueException("Labels are read-only objects that can't be changed");
                isLegal = false;
            }
            var vector2 = control as UI_Vector2;

            if (vector2 != null)
            {
                // I have no clue what this actually looks like in the UI?  What is a
                // user editable 2-D vector widget?  I've never seen this before.
                if (convertedVal != null)
                {
                    var vec2 = (Vector2)convertedVal;
                    if (vec2.x < vector2.minValueX || vec2.x > vector2.maxValueX ||
                        vec2.y < vector2.minValueY || vec2.y > vector2.maxValueY)
                    {
                        except  = new KOSInvalidFieldValueException("Vector2 is outside of allowed range of values");
                        isLegal = false;
                    }
                }
            }
            var range = control as UI_FloatRange;

            if (range != null)
            {
                float val = Convert.ToSingle(convertedVal);
                val          = KOSMath.ClampToIndent(val, range.minValue, range.maxValue, range.stepIncrement);
                convertedVal = Convert.ToDouble(val);
            }
            newVal = FromPrimitiveWithAssert(convertedVal);
            return(isLegal);
        }
コード例 #2
0
        /// <summary>
        /// Return true if the value given is allowed for the field given.  This uses the hints from the GUI
        /// system to decide what is and isn't allowed.  (For example if a GUI slider goes from 10 to 20 at
        /// increments of 2, then a value of 17 is not something you could achieve in the GUI, being only able
        /// to go from 16 to 18 skipping over 17, and therefore this routine would return false for trying to
        /// set it to 17).
        /// <br/><br/>
        /// Note that the value passed in may be altered (which is why it's ref) when it's not
        /// exactly legal, but it's CLOSE ENOUGH to be coerced into a legal value.  For example,
        /// you set a slider to 10.45 and the slider only allows values on the 0.5 marks like 10, 10.5, 11. etc.
        /// Rather than deny the attempt, the value will be nudged to the nearest legal value.
        /// </summary>
        /// <param name="field">Which KSPField is being checked?</param>
        /// <param name="newVal">What is the value it's being set to?  It is possible to
        ///    alter the value to an acceptable replacement which is why it passes by ref</param>
        /// <param name="except">An exception you can choose to throw if you want, or null if the value is legal.</param>
        /// <returns>Is it legal?</returns>
        private bool IsLegalValue(BaseField field, ref object newVal, out KOSException except)
        {
            except = null;
            bool isLegal = true;

            Type   fType        = field.FieldInfo.FieldType;
            object convertedVal = newVal;

            if (!IsEditable(field))
            {
                except = new KOSInvalidFieldValueException("Field is read-only");
                return(false);
            }
            if (!newVal.GetType().IsSubclassOf(fType))
            {
                try
                {
                    convertedVal = Convert.ChangeType(newVal, fType);
                }
                catch (InvalidCastException)
                {
                    except = new KOSCastException(newVal.GetType(), fType);
                    return(false);
                }
                catch (FormatException)
                {
                    except = new KOSCastException(newVal.GetType(), fType);
                    return(false);
                }
            }
            List <UI_Control> controls = GetFieldControls(field);

            // It's really normal for there to be only one control on a KSPField, but because
            // it's technically possible to have more than one according to the structure of
            // the API, this loop is here to check all of "them":
            foreach (UI_Control control in controls)
            {
                // Some of these are subclasses of each other, so don't change this to an if/else.
                // It's a series of if's on purpose so it checks all classes the control is derived from.
                if (control is UI_Toggle)
                {
                    // Seems there's nothing to check here, but maybe later there will be?
                }
                if (control is UI_Label)
                {
                    except  = new KOSInvalidFieldValueException("Labels are read-only objects that can't be changed");
                    isLegal = false;
                }
                var vector2 = control as UI_Vector2;
                if (vector2 != null)
                {
                    // I have no clue what this actually looks like in the UI?  What is a
                    // user editable 2-D vector widget?  I've never seen this before.
                    if (convertedVal != null)
                    {
                        var vec2 = (Vector2)convertedVal;
                        if (vec2.x < vector2.minValueX || vec2.x > vector2.maxValueX ||
                            vec2.y < vector2.minValueY || vec2.y > vector2.maxValueY)
                        {
                            except  = new KOSInvalidFieldValueException("Vector2 is outside of allowed range of values");
                            isLegal = false;
                        }
                    }
                }
                var range = control as UI_FloatRange;
                if (range != null)
                {
                    float val = Convert.ToSingle(convertedVal);
                    val          = Math.ClampToIndent(val, range.minValue, range.maxValue, range.stepIncrement);
                    convertedVal = Convert.ToDouble(val);
                }
                if (!isLegal)
                {
                    break;
                }
            }
            newVal = convertedVal;
            return(isLegal);
        }