/// <summary>Fixes null persistent fields in the module.</summary>
 /// <remarks>Used to prevent NREs in methods that persist KSP fields.</remarks>
 /// <param name="module">Module to fix.</param>
 public static void CleanupFieldsInModule(PartModule module)
 {
     // Ensure the module is awaken. Otherwise, any access to base fields list will result in NRE.
     // HACK: Accessing Fields property of a non-awaken module triggers NRE. If it happens then do
     // explicit awakening of the *base* module class.
     try {
         var unused = module.Fields.GetEnumerator();
     } catch {
         Logger.logWarning("WORKAROUND. Module {0} on part prefab {1} is not awaken. Call Awake on it",
                           module.GetType(), module.part);
         AwakePartModule(module);
     }
     foreach (var field in module.Fields)
     {
         var baseField = field as BaseField;
         if (baseField.isPersistant && baseField.GetValue(module) == null)
         {
             var proto    = new StandardOrdinaryTypesProto();
             var defValue = proto.ParseFromString("", baseField.FieldInfo.FieldType);
             Logger.logWarning("WORKAROUND. Found null field {0} in module prefab {1},"
                               + " fixing to default value of type {2}: {3}",
                               baseField.name,
                               module.moduleName,
                               baseField.FieldInfo.FieldType,
                               defValue);
             baseField.SetValue(defValue, module);
         }
     }
 }
Пример #2
0
 /// <summary>Fixes null persistent fields in the module.</summary>
 /// <remarks>Used to prevent NREs in methods that persist KSP fields.</remarks>
 /// <param name="module">A module to fix.</param>
 public static void CleanupFieldsInModule(PartModule module)
 {
     foreach (var field in module.Fields)
     {
         var baseField = field as BaseField;
         if (baseField.isPersistant && baseField.GetValue(module) == null)
         {
             var proto    = new StandardOrdinaryTypesProto();
             var defValue = proto.ParseFromString("", baseField.FieldInfo.FieldType);
             Logger.logWarning("WORKAROUND. Found null field {0} in module prefab {1},"
                               + " fixing to default value of type {2}: {3}",
                               baseField.name,
                               module.moduleName,
                               baseField.FieldInfo.FieldType,
                               defValue);
             baseField.SetValue(defValue, module);
         }
     }
 }
Пример #3
0
        /// <summary>Fixes null persistent fields in the module.</summary>
        /// <remarks>Used to prevent NREs in methods that persist KSP fields.</remarks>
        /// <param name="module">The module to fix.</param>
        static void CleanupFieldsInModule(PartModule module)
        {
            // HACK: Fix uninitialized fields in science lab module.
            var scienceModule = module as ModuleScienceLab;

            if (scienceModule != null)
            {
                scienceModule.ExperimentData = new List <string>();
                DebugEx.Warning(
                    "WORKAROUND. Fix null field in ModuleScienceLab module on the part prefab: {0}", module);
            }

            // Ensure the module is awaken. Otherwise, any access to base fields list will result in NRE.
            // HACK: Accessing Fields property of a non-awaken module triggers NRE. If it happens then do
            // explicit awakening of the *base* module class.
            try {
                module.Fields.GetEnumerator();
            } catch {
                DebugEx.Warning(
                    "WORKAROUND. Module {0} on part prefab is not awaken. Call Awake on it", module);
                module.Awake();
            }
            foreach (var field in module.Fields)
            {
                var baseField = field as BaseField;
                if (baseField.isPersistant && baseField.GetValue(module) == null)
                {
                    var proto    = new StandardOrdinaryTypesProto();
                    var defValue = proto.ParseFromString("", baseField.FieldInfo.FieldType);
                    DebugEx.Warning("WORKAROUND. Found null field {0} in module prefab {1},"
                                    + " fixing to default value of type {2}: {3}",
                                    baseField.name, module, baseField.FieldInfo.FieldType, defValue);
                    baseField.SetValue(defValue, module);
                }
            }
        }
Пример #4
0
        /// <summary>Creates a debug adjustment control for the basic type.</summary>
        /// <param name="caption">The field caption to show in the dialog.</param>
        /// <param name="instance">
        /// The instance of the object that holds the field to be adjusted via GUI.
        /// </param>
        /// <param name="host">
        /// The class that should get the member change notifications. If not set, then
        /// <paramref name="instance"/> will be the target.
        /// </param>
        /// <param name="fieldInfo">The field info of the target member.</param>
        /// <param name="propertyInfo">The property info of the target member.</param>
        /// <param name="methodInfo">The action member info.</param>
        public StdTypesDebugGuiControl(string caption, object instance,
                                       IHasDebugAdjustables host = null,
                                       FieldInfo fieldInfo       = null,
                                       PropertyInfo propertyInfo = null,
                                       MethodInfo methodInfo     = null)
        {
            Action onBeforeValueUpdateCallback = null;
            Action onAfterValueUpdateCallback  = null;
            var    adjustable = (host as IHasDebugAdjustables)
                                ?? (instance as IHasDebugAdjustables);

            if (adjustable != null)
            {
                onBeforeValueUpdateCallback = adjustable.OnBeforeDebugAdjustablesUpdate;
                onAfterValueUpdateCallback  = adjustable.OnDebugAdjustablesUpdated;
            }
            try {
                if (methodInfo != null)
                {
                    if (methodInfo.GetParameters().Length > 0)
                    {
                        throw new ArgumentException("Debug action method must be parameterless");
                    }
                    this.caption = caption;
                    this.action  = () => methodInfo.Invoke(instance, new object[0]);
                }
                else
                {
                    this.caption = caption + ":";
                    this.action  = null;
                    var type = fieldInfo != null ? fieldInfo.FieldType : propertyInfo.PropertyType;
                    if (type == typeof(bool))
                    {
                        this.control = new HermeticGUIControlBoolean(
                            caption, instance,
                            fieldInfo: fieldInfo, propertyInfo: propertyInfo,
                            onBeforeUpdate: onBeforeValueUpdateCallback,
                            onAfterUpdate: onAfterValueUpdateCallback);
                    }
                    else if (type.IsEnum)
                    {
                        this.control = new HermeticGUIControlSwitch(
                            instance,
                            fieldInfo: fieldInfo, propertyInfo: propertyInfo,
                            onBeforeUpdate: onBeforeValueUpdateCallback,
                            onAfterUpdate: onAfterValueUpdateCallback,
                            useOwnLayout: false);
                    }
                    else
                    {
                        var proto = new StandardOrdinaryTypesProto();
                        if (proto.CanHandle(type))
                        {
                            this.control = new HermeticGUIControlText(
                                instance,
                                fieldInfo: fieldInfo, propertyInfo: propertyInfo,
                                onBeforeUpdate: onBeforeValueUpdateCallback,
                                onAfterUpdate: onAfterValueUpdateCallback,
                                useOwnLayout: false);
                        }
                        else
                        {
                            this.control = new HermeticGUIControlClass(
                                caption, instance,
                                fieldInfo: fieldInfo, propertyInfo: propertyInfo,
                                onBeforeUpdate: onBeforeValueUpdateCallback,
                                onAfterUpdate: onAfterValueUpdateCallback);
                        }
                    }
                }
            } catch (Exception ex) {
                if (fieldInfo != null)
                {
                    DebugEx.Error(
                        "Failed to bind to field {0}.{1} => {2}: {3}",
                        fieldInfo.DeclaringType.FullName, fieldInfo.Name, fieldInfo.FieldType, ex);
                }
                else if (propertyInfo != null)
                {
                    DebugEx.Error(
                        "Failed to bind to property {0}.{1} => {2}: {3}",
                        propertyInfo.DeclaringType.FullName, propertyInfo.Name, propertyInfo.PropertyType, ex);
                }
                else
                {
                    DebugEx.Error(
                        "Failed to bind to method {0}.{1} => {2}: {3}",
                        methodInfo.DeclaringType.FullName, methodInfo.Name, methodInfo.ReturnType, ex);
                }
            }
        }