diff --git a/Binaries/KSPDev_Utils.0.21.0.dll b/Binaries/KSPDev_Utils.0.21.0.dll deleted file mode 100644 index db45c438..00000000 Binary files a/Binaries/KSPDev_Utils.0.21.0.dll and /dev/null differ diff --git a/Binaries/KSPDev_Utils.0.22.1.dll b/Binaries/KSPDev_Utils.0.22.1.dll new file mode 100644 index 00000000..45fb278a Binary files /dev/null and b/Binaries/KSPDev_Utils.0.22.1.dll differ diff --git a/Binaries/KSPDev_Utils.0.21.0.xml b/Binaries/KSPDev_Utils.0.22.1.xml similarity index 88% rename from Binaries/KSPDev_Utils.0.21.0.xml rename to Binaries/KSPDev_Utils.0.22.1.xml index cf1b87b0..f7a95ed5 100644 --- a/Binaries/KSPDev_Utils.0.21.0.xml +++ b/Binaries/KSPDev_Utils.0.22.1.xml @@ -1,7 +1,7 @@ - KSPDev_Utils.0.21.0 + KSPDev_Utils.0.22.1 @@ -209,6 +209,78 @@ group will be considered. Must not be null. + + Interface for the simple types that need custom (de)serialization logic. + + It's similar to IConfigNode interface in the compound types but with the following + differences: + + The value is (de)serialized from/to a simple string. + + If the field is initialized to an instance of the type, then this instance will be used to + deserialize the value. If the field is not initialized but there is a value in the config file, + then a new instance will be created. For this reason the type must implement a default + constructor. + + + + Note that the types that implement this interface will never be treated as compound. I.e. + will not try to persist the members of such types even though there + may be fields attributed with . + + + + Here is how a simple vector serialization may look like: + + public string SerializeToString() { + return string.Format("{0},{1}", x ,y); + } + /// + public void ParseFromString(string value) { + var elements = value.Split(','); + x = float.Parse(elements[0]); + y = float.Parse(elements[1]); + } + } + ]]> + + This example doesn't do any checking when parsing the string, but in general it's a good idea to + do a sanity check of the string. It's OK to throw an exception from the parsing method when the + data is invalid. + + + + + + + Returns the object's state as a plain string. + Object's state. + + + Restores the object's state from a plain string. + String value to restore from. + It's OK to throw exceptions if the value cannot be parsed. + + + Helper methods to access and manipulate part's configs. + + + Gets a config of the part module. + + It takes into account the module index, so in case of the part has multiple modules of the + same type, the right module config will be returned. + + Module to get config for. + + Part's config to use. If omitted then part's prefab config is used. + + Either the found config node or an empty node. It's never null. + A simple annotation to associate a persistent group with a game's database key. @@ -775,170 +847,191 @@ New configuration node with the data. - Sets compound type field values from the config node. + Sets a compound type field values from the config node. Node to read values from. Owner of the fields. - A simple attribute for fields that need (de)serialization. - - This form allows adjusting any property - in the annotation, and has a shortcut to mark a field as collection - ( = true). - - By default ordinal values are handled via - and collection fields via . These proto handlers can - be changed in the annotation by assigning values to properties - and/or . - - - - Below is a simple usage of the attribute. - sampleList = new List(); - - internal struct ComplexType { - [PersistentField("val1", group = "nevermind")] - public bool boolVal; - [PersistentField("val2")] - public Color colorVal; - } - - [PersistentField("my/setField", isCollection = true, group = "abc")] - private HashSet sampleSet = new HashSet(); - - void SaveConfigs() { - // Save a default group of fields: only field "sampleList" qualifies. - ConfigAccessor.WriteFieldsIntoFile("settings.cfg", instance: this); - /* The following structure in the file will be created: - * { - * my - * { - * listField: string1 - * listField: string2 - * } - * } - */ - - // Save a specific group of fields: only field "sampleSet" belongs to group "abc". - sampleSet.Add(new ComplexType() { boolVal = true, colorVal = Color.black }); - sampleSet.Add(new ComplexType() { boolVal = false, colorVal = Color.white }); - ConfigAccessor.WriteFieldsIntoFile("settings.cfg", instance: this, group: "abc"); - /* The following structure in the file will be created: - * { - * setField - * { - * val1: True - * val2: 0,0,0,1 - * } - * setField - * { - * val1: false - * val2: 1,1,1,1 - * } - * } - * } - */ - } - } - ]]> - - Note that group is ignored in the nested types. I.e. in ComplexType in this case. Though, - if ComplexType was an immediate target of the WriteFieldsIntoFile call then the - group would be considered. - - - Visibility of the annotated field is also important. Persistent field attributes are only - visible in the child class if they were public or protected in the parent. Private field - annotations are not inherited and need to be handled at the level of the declaring class. - - A simple attribute for the fields that need (de)serialization. + + This form allows adjusting any property + in the annotation, and has a shortcut to mark a field as a collection + ( = true). + + By default the ordinal values are handled via + and the collection fields via . These proto handlers can + be changed in the annotation by assigning properties + and/or . + + + + Below is a simple usage of the attribute. + sampleList = new List(); + + internal struct ComplexType { + [PersistentField("val1", group = "nevermind")] + public bool boolVal; + [PersistentField("val2")] + public Color colorVal; + } + + [PersistentField("my/setField", isCollection = true, group = "abc")] + private HashSet sampleSet = new HashSet(); + + void SaveConfigs() { + // Save a default group of fields: only field "sampleList" qualifies. + ConfigAccessor.WriteFieldsIntoFile("settings.cfg", instance: this); + /* The following structure in the file will be created: + * { + * my + * { + * listField: string1 + * listField: string2 + * } + * } + */ + + // Save a specific group of fields: only field "sampleSet" belongs to group "abc". + sampleSet.Add(new ComplexType() { boolVal = true, colorVal = Color.black }); + sampleSet.Add(new ComplexType() { boolVal = false, colorVal = Color.white }); + ConfigAccessor.WriteFieldsIntoFile("settings.cfg", instance: this, group: "abc"); + /* The following structure in the file will be created: + * { + * setField + * { + * val1: True + * val2: 0,0,0,1 + * } + * setField + * { + * val1: false + * val2: 1,1,1,1 + * } + * } + * } + */ + } + } + ]]> + + Note that the group is ignored in the nested types. I.e. in ComplexType in this case. + However, if ComplexType was an immediate target of the WriteFieldsIntoFile call + then the group would be considered. + + + Visibility of the annotated field is also important. The persistent field attributes are only + visible in the child class if they were public or protected in the parent. The private field + annotations are not inherited and need to be handled at the level of the declaring class. + + + + The code above implies that in a common case unsealed class should put the private fields in a + group other than default to avoid settings collision. + + + When the type of the field is different from a primitive C# type or a common Unity 4 type you + may need to provide a custom value handler to deal with (de)serializing. E.g. for an ordinary + type it may look like this: + + + + Or your custom class can implement a KSP interface , and it will be + invoked during the field saving and restoring. + + + + It's important to note that complex (a.k.a. "compound") types like this are only handled when + the field's value is not null. I.e. in the following example the value of field1 + will not be restored even if there is a node in the config file: + + - - The code above implies that in a common case unsealed class should put private fields in a group - other than default to avoid settings collision. - - - When type of the field is different from primitive C# type or common Unity 4 type you may need - provide custom value handlers to deal with (de)serializing. E.g. for an ordinary type it may - look like this: - - - - Or you custom class can implement KSP interface , and it will be - invoked during field saving and restoring. - - - - If your custom type is a collection that cannot be handled by the standard proto you can provide - your own collection proto handler. Note that if you do then annotated field will be treated as a - collection. In fact, when you set isCollection = true what actually happens is just - assigning as a collection proto handler. - - } - - For more examples on custom proto handlers see and - . - - - - - KSP: IConfigNode + [PersistentField("field2")] + public NodeCustomType field2 = new NodeCustomType(); + } + ]]> + + In case of your type is really simple, and you can serialize it into a plain string, you may + choose to implement instead. It works in a similar way but the + source/target of the persistense is a string instead of a config node. Simple types deal with + null's in a different way (read the docs for the interface). + + + If your custom type is a collection that cannot be handled by the standard proto you can provide + your own collection proto handler. Note that if you do then the annotated field will be treated + as a collection. In fact, when you set isCollection = true what actually happens is just + assigning as a collection proto handler. + + + For more examples on custom proto handlers see and + . + + + + + + KSP: IConfigNode @@ -1137,19 +1230,19 @@ A class to wrap a UI string for an enum value. - Enum type to define strings for. + Enum type to define the strings for. - When string needs to be presented use to make the parameter substitute. + When a string needs to be presented, use to make the parameter substitute. In the future it may support localization but for now it's only a convinience wrapper. - Instead of doing switches when an enum value should be presented on UI just define a message - that declares a map between values and their UI representations. You don't need specify every - single value in the map, there is an option to set a UI string for unknown value. + Instead of doing switches when an enum value should be presented on UI, just define a message + that declares a map between the values and their UI representations. You don't need to specify + every single value in the map, there is an option to set a UI string for an unknown value. Msg1 = new MessageEnumValue("UNKNOWN") { {MyEnum.Enabled, "ENABLED"}, {MyEnum.Disabled, "DISABLED"}, }; - // Default lookup. + // A more extended lookup. static readonly MessageEnumValue Msg2 = new MessageEnumValue() { {MyEnum.Enabled, "ENABLED"}, @@ -1189,13 +1282,14 @@ - Creates an empty message with a default value for unknow entries. + Creates an empty message with a default value for the unknown entries. - Value to return if lookup dictionary doesn't have the requested key. + Value to return if the lookup dictionary doesn't have the requested key. - + Returns a key/pair enumerator. + Key/value enumerator. Adds a new lookup for the key. @@ -1203,10 +1297,14 @@ GUI string for the key. - Formats message string with the provided arguments. + Formats a message string with the provided arguments. An argument to substitute. Complete message string. + + Returns an untyped key/value enumerator. + Key/value enumerator. + A class to wrap a UI string with one parameter which may have special meaning. @@ -2498,37 +2596,52 @@ into a human readable string. A collection to represent as a string. A predicate to use to extract string representation of an item. If - String to use to glue the parts. null then standard ToString() is used. + String to use to glue the parts. Human readable form of the collection. Collection's item type. + + Helper methods to align transformations relative to each other. + + + + Aligns the source node so that it's located at the target, and source and target are "looking" + at each other. + + Node to align. + Child node of the source to use as the align point. + Target node to align with. + Various tools to deal with procedural colliders. - Drops colliders in all children objects, and adds one big collider to the parent. + + Drops the colliders in all the children objects, and adds one big collider to the parent. - Intended to create one fast collider at the cost of precision. All the meshes in the parent - childs (including the parent) are processed to produce a boundary box. Then, this box is - applied to the requested primitive type that defines the shape of the collider. + The main purpose of this method is to create one fast collider at the cost of precision. All + the meshes in the object (the parent and the children) are processed to produce a single + boundary box. Then, this box is applied to the requested primitive type that defines the shape + of the final collider. - Note, that rdaius if sphere and capsule is the same in both X and Y axis. If combined boundary - box has any of the dimensions significantly different then it makes sense to choose a - different collider type. Or break down the hirearchy into more colliders. + Note, that radius of the sphere and the capsule colliders is the same on both X and Y axis. + If the combined boundary box has any of the dimensions significantly different then it makes + sense to choose a different collider type. Or break down the hirearchy into more colliders. Parent object. - Type of the primitive mesh which is the best for wrapping all the meshes of the object. Only - , , and - are supported. + Type of the primitive which describes the parent object most precise in terms of the shape. + Only , , + , and are supported. + The two latter types produce in the same collider type - the capsule. - If true then collider will define the outer boundaries so what all the meshes are - inside the volume. Otherwise, the combined meshes box will define the outer boundary of the - collider. It only makes sense for the colliders other than . + When calculating the total volume of the object, all its meshes produce a single box boundary. + Then, the collider either wraps this box entirely, or sits inside it entirely. If this + parameter is true then the collider will cover the boundary box. Unity 3D: GameObject @@ -2565,6 +2678,37 @@ are supported. + + Disables/enables all the colliders between the objects. + + All colliders in all the children of the both objects are explicitly set to not collide with + each other. The ignore state is reset to false on every scene load. + + Source object. + Target object. + + If true then the collisions between the objects will be ignored. Otherwise, the + collisions will be handled. + + + Unity3D: Collider + + Unity3D: Physics.IgnoreCollision + + + Disables/enables all the colliders between the parts. + The ignore state is reset to false on every scene load. + Source part. + Target part. + + If true then the collisions between the parts will be ignored. Otherwise, the + collisions will be handled. + + + Unity3D: Collider + + Unity3D: Physics.IgnoreCollision + Defines how collisions should be checked on a primitive. @@ -2871,19 +3015,19 @@ Translates meshes's verticies. This is different from setting postion, rotation and scale to the transform. This method - actually changes vetricies in the mesh. It's not performance effective, so avoid doing it - frequiently. + actually changes vetricies in the mesh. It's not performance effective, so avoid doing + it frequiently. - Model object to change mesh in. + Model object to change the mesh in. - Offset for the verticies. If not specified then offset is zero. Offset is added after - scale and rotation have been applied. + Offset for the verticies. If not specified then the offset is zero. The offset is added + after the scale and the rotation have been applied. Rotation for the verticies. If not set then no rotation is added. - Scale for the vertex positions. If not specified then scale is not affected. + Scale for the vertex positions. If not specified then the scale is not affected. @@ -2985,7 +3129,7 @@ Unity object to run coroutine on. If this object dies then waiting will be aborted without calling any callbacks. - Number of fixed frame update to wait before giving up. + Number of fixed frame updates to wait before giving up. State checking function. It should return true once target state is reached. The very first execution happens immediately, before exiting from the method. If this @@ -3033,13 +3177,30 @@ ]]> If you adjust count to 11 then the last message will be "Failure!". + Unity 3D: Coroutines Unity 3D: WaitForFixedUpdate Async version of . - Enumerator that can be used as coroutine target. + Number of fixed frame updates to wait before giving up. + + State checking function. It should return true once target state is reached. The very + first execution happens immediately, before exiting from the method. If this + this execution returned true then the successful callback is also called immediately. + + Callback to execute when state has been successfully reached. + + Callabck to execute when state has not been reached before frame update limit is exhausted. + + + Callback to execute every fixed frame update while waiting. This callabck will be called at + least once, and teh first call happens immediately. The argument tells how many frames the + method was waiting so far. For the very first call it's, obviously, zero. + + When true every wiating cycle will be logged. + Enumerator that can be used as a coroutine target. This method is useful when synchronous wait is needed within a coroutine. Instead of @@ -3322,6 +3483,74 @@ State before change. State after change. + + Type to hold position and rotation of a transform. It can be serialized. + + The value serializes into 6 numbers separated by a comma. They form two triplets: + + The first triplet is a position: x, y, z. + + The second triplet is a Euler rotaion around each axis: x, y, z. + + + + + + Position of the transform. + + + Constructs a default instance. + Required for the persistence to work correctly. + + By default position is (0,0,0), Euler angles are (0,0,0), and the rotation is + Quaternion.identity. + + + Unity3D: Vector3 + + Unity3D: Quaternion + + + Constructs a copy of an object of the same type. + Source object. + + + Constructs an object from a transform properties. + Position of the transform. + Euler rotation of the transform. + + Unity3D: Vector3 + + Unity3D: Transform + + + Gives a deep copy of the object. + New object. + + + + + + + + + Shows a human readable representation. + String value. + + + + Ensures that all the angles are in the range of [0; 360). + + + + Euler rotation. + + The rotation angles are automatically adjusted to stay within the [0; 360) range. + + + + Orientation of the transform. + Debugging class that reports which DLL was actually loaded for the Utils assembly. diff --git a/Source/KIS.csproj b/Source/KIS.csproj index 39791ba6..96e37972 100644 --- a/Source/KIS.csproj +++ b/Source/KIS.csproj @@ -40,8 +40,8 @@ Q:\KSP_Data\Managed\Assembly-CSharp-firstpass.dll False - - ..\Binaries\KSPDev_Utils.0.21.0.dll + + ..\Binaries\KSPDev_Utils.0.22.1.dll