├── .gitignore ├── .npmignore ├── Artees.meta ├── Artees ├── UnitySemVer.meta └── UnitySemVer │ ├── Artees.UnitySemVer.asmdef │ ├── Artees.UnitySemVer.asmdef.meta │ ├── CloudBuildManifest.cs │ ├── CloudBuildManifest.cs.meta │ ├── Editor.meta │ ├── Editor │ ├── Artees.UnitySemVer.Editor.asmdef │ ├── Artees.UnitySemVer.Editor.asmdef.meta │ ├── SemVerAttributeDrawer.cs │ ├── SemVerAttributeDrawer.cs.meta │ ├── SemVerDrawer.cs │ ├── SemVerDrawer.cs.meta │ ├── SemVerTooltip.cs │ └── SemVerTooltip.cs.meta │ ├── SemVer.cs │ ├── SemVer.cs.meta │ ├── SemVerAttribute.cs │ ├── SemVerAttribute.cs.meta │ ├── SemVerAutoBuild.cs │ ├── SemVerAutoBuild.cs.meta │ ├── SemVerComparer.cs │ ├── SemVerComparer.cs.meta │ ├── SemVerConverter.cs │ ├── SemVerConverter.cs.meta │ ├── SemVerErrorMessage.cs │ ├── SemVerErrorMessage.cs.meta │ ├── SemVerValidationResult.cs │ ├── SemVerValidationResult.cs.meta │ ├── SemVerValidator.cs │ ├── SemVerValidator.cs.meta │ ├── Tests.meta │ └── Tests │ ├── Artees.UnitySemVer.Tests.asmdef │ ├── Artees.UnitySemVer.Tests.asmdef.meta │ ├── SemVerTests.cs │ ├── SemVerTests.cs.meta │ ├── SuggestedRegEx.cs │ └── SuggestedRegEx.cs.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── Scenes.meta ├── Scenes ├── SampleScene.unity └── SampleScene.unity.meta ├── Scripts.meta ├── Scripts ├── SemVerDrawerTest.cs └── SemVerDrawerTest.cs.meta ├── SemVerDrawer.png ├── SemVerDrawer.png.meta ├── UnityCloud.meta ├── UnityCloud ├── Resources.meta └── Resources │ ├── TestUnityCloudBuildManifest.json.txt │ └── TestUnityCloudBuildManifest.json.txt.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | *.opendb 26 | 27 | # Unity3D generated meta files 28 | *.pidb.meta 29 | *.pdb.meta 30 | 31 | # Unity3D Generated File On Crash Reports 32 | sysinfo.txt 33 | 34 | # Builds 35 | *.apk 36 | *.unitypackage 37 | 38 | .idea/ 39 | Logs/ 40 | Research/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | Scenes/ 3 | Scenes.meta 4 | Scripts/ 5 | Scripts.meta 6 | UnityCloud/ 7 | UnityCloud.meta -------------------------------------------------------------------------------- /Artees.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 484d4966092966e45a28a9d6cc91c204 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Artees/UnitySemVer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3388dbc96970c8488199044b3469159 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Artees.UnitySemVer.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Artees.SemanticVersioning" 3 | } 4 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Artees.UnitySemVer.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c7f2f2911de381941be7186214305448 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/CloudBuildManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Artees.UnitySemVer 5 | { 6 | /// 7 | /// A parsed Unity Cloud Build manifest. 8 | /// 9 | internal class CloudBuildManifest 10 | { 11 | private static CloudBuildManifest _instance; 12 | 13 | public static CloudBuildManifest Instance => _instance ?? (_instance = new CloudBuildManifest()); 14 | 15 | /// 16 | /// Returns true if the manifest has been successfully loaded. 17 | /// 18 | public readonly bool IsLoaded; 19 | 20 | /// 21 | /// The Unity Cloud Build “build number” corresponding to this build. 22 | /// 23 | public readonly int BuildNumber; 24 | 25 | private CloudBuildManifest() 26 | { 27 | var manifestAsset = Resources.Load("UnityCloudBuildManifest.json"); 28 | if (manifestAsset == null) return; 29 | var manifest = manifestAsset.text; 30 | IsLoaded = true; 31 | const string key = "\"buildNumber\""; 32 | const StringComparison comparison = StringComparison.Ordinal; 33 | var keyStart = manifest.IndexOf(key, comparison); 34 | var valueStart = manifest.IndexOf("\"", keyStart + key.Length, comparison) + 1; 35 | var valueEnd = manifest.IndexOf("\"", valueStart, comparison); 36 | var buildNumber = manifest.Substring(valueStart, valueEnd - valueStart); 37 | int.TryParse(buildNumber, out BuildNumber); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/CloudBuildManifest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67911a38e15b9234eaf8f5d496ce8f4a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e638df7023a2b8439628efa6bb59101 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/Artees.UnitySemVer.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Artees.SemanticVersioning.Editor", 3 | "references": [ 4 | "GUID:c7f2f2911de381941be7186214305448" 5 | ], 6 | "optionalUnityReferences": [], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [] 17 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/Artees.UnitySemVer.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 308df40f6e652514f83f076a940c584d 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerAttributeDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Artees.UnitySemVer.Editor 5 | { 6 | [CustomPropertyDrawer(typeof(SemVerAttribute))] 7 | internal class SemVerAttributeDrawer : SemVerDrawer 8 | { 9 | public SemVerAttributeDrawer() 10 | { 11 | DrawAutoBuildPopup = false; 12 | } 13 | 14 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 15 | { 16 | if (property.type == "string") 17 | { 18 | Target = SemVer.Parse(property.stringValue); 19 | var corrected = DrawSemVer(position, property, label); 20 | property.stringValue = corrected.ToString(); 21 | return; 22 | } 23 | 24 | Debug.LogWarning($"{property.type} is not supported by {this}"); 25 | EditorGUI.BeginProperty(position, label, property); 26 | EditorGUI.PropertyField(position, property); 27 | EditorGUI.EndProperty(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerAttributeDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 023d0bd3adca7fe4780d4bda000fb144 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerDrawer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Artees.UnitySemVer.Editor 6 | { 7 | [CustomPropertyDrawer(typeof(SemVer))] 8 | internal class SemVerDrawer : PropertyDrawer 9 | { 10 | private const float IncrementButtonWidth = 40f; 11 | 12 | private float _yMin; 13 | private Rect _position; 14 | 15 | protected SemVer Target { private get; set; } 16 | protected bool DrawAutoBuildPopup { private get; set; } 17 | 18 | public SemVerDrawer() 19 | { 20 | DrawAutoBuildPopup = true; 21 | } 22 | 23 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 24 | { 25 | var targetObject = property.serializedObject.targetObject; 26 | var source = fieldInfo.GetValue(targetObject) as SemVer; 27 | if (source == null) return; 28 | Target = source.Clone(); 29 | var corrected = DrawSemVer(position, property, label); 30 | if (corrected == source && corrected.autoBuild == source.autoBuild) return; 31 | EditorUtility.SetDirty(targetObject); 32 | fieldInfo.SetValue(targetObject, corrected); 33 | } 34 | 35 | protected SemVer DrawSemVer(Rect position, SerializedProperty property, GUIContent label) 36 | { 37 | InitPosition(position); 38 | property.isExpanded = 39 | EditorGUI.Foldout(GetNextPosition(), property.isExpanded, $"{label.text} {Target}", true); 40 | if (!property.isExpanded) return Target; 41 | EditorGUI.indentLevel++; 42 | CreateMajorField(); 43 | CreateMinorField(); 44 | CreatePatchField(); 45 | CreatePreReleaseField(); 46 | CreateBuildField(); 47 | var corrected = Validate(); 48 | EditorGUI.indentLevel--; 49 | return corrected; 50 | } 51 | 52 | private void InitPosition(Rect position) 53 | { 54 | _yMin = position.yMin; 55 | _position = position; 56 | _position.height = EditorGUIUtility.singleLineHeight; 57 | _position.y -= EditorGUIUtility.singleLineHeight; 58 | } 59 | 60 | private Rect GetNextPosition() 61 | { 62 | _position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; 63 | return _position; 64 | } 65 | 66 | private void CreateMajorField() 67 | { 68 | const string label = SemVerTooltip.Major; 69 | Target.major = CreateCoreField(label, Target.major); 70 | if (CreateIncrementButton(label)) Target.IncrementMajor(); 71 | } 72 | 73 | private void CreateMinorField() 74 | { 75 | const string label = SemVerTooltip.Minor; 76 | Target.minor = CreateCoreField(label, Target.minor); 77 | if (CreateIncrementButton(label)) Target.IncrementMinor(); 78 | } 79 | 80 | private void CreatePatchField() 81 | { 82 | const string label = SemVerTooltip.Patch; 83 | Target.patch = CreateCoreField(label, Target.patch); 84 | if (CreateIncrementButton(label)) Target.IncrementPatch(); 85 | } 86 | 87 | private uint CreateCoreField(string label, uint version) 88 | { 89 | uint newVersionUint; 90 | try 91 | { 92 | var position = GetNextPosition(); 93 | position.width -= IncrementButtonWidth + EditorGUIUtility.standardVerticalSpacing; 94 | var content = CreateGuiContentWithTooltip(label); 95 | var newVersionInt = EditorGUI.IntField(position, content, (int) version); 96 | newVersionUint = Convert.ToUInt32(newVersionInt); 97 | } 98 | catch (OverflowException) 99 | { 100 | Debug.LogWarning("A version must not be negative"); 101 | newVersionUint = version; 102 | } 103 | 104 | return newVersionUint; 105 | } 106 | 107 | private static GUIContent CreateGuiContentWithTooltip(string label) 108 | { 109 | return new GUIContent(label, SemVerTooltip.Field[label]); 110 | } 111 | 112 | private bool CreateIncrementButton(string version) 113 | { 114 | var buttonName = GUID.Generate().ToString(); 115 | GUI.SetNextControlName(buttonName); 116 | var position = _position; 117 | position.width = IncrementButtonWidth; 118 | position.x += _position.width - IncrementButtonWidth; 119 | var content = new GUIContent("+", SemVerTooltip.Increment[version]); 120 | var isClicked = GUI.Button(position, content); 121 | if (isClicked) GUI.FocusControl(buttonName); 122 | return isClicked; 123 | } 124 | 125 | private void CreatePreReleaseField() 126 | { 127 | var position = GetNextPosition(); 128 | var content = CreateGuiContentWithTooltip(SemVerTooltip.PreRelease); 129 | Target.preRelease = EditorGUI.TextField(position, content, Target.preRelease); 130 | } 131 | 132 | private void CreateBuildField() 133 | { 134 | var position = GetNextPosition(); 135 | var content = CreateGuiContentWithTooltip(SemVerTooltip.Build); 136 | if (DrawAutoBuildPopup) 137 | { 138 | var popupPosition = position; 139 | var popupWidth = EditorGUIUtility.labelWidth + 120f; 140 | popupPosition.width = popupWidth; 141 | var selected = EditorGUI.EnumPopup(popupPosition, content, Target.autoBuild); 142 | Target.autoBuild = (SemVerAutoBuild.Type) selected; 143 | var textPosition = position; 144 | textPosition.x = popupWidth + EditorGUIUtility.standardVerticalSpacing; 145 | textPosition.width -= textPosition.x - 14f; 146 | if (SemVerAutoBuild.Instances[Target.autoBuild] is SemVerAutoBuild.ReadOnly) 147 | { 148 | var guiEnabled = GUI.enabled; 149 | GUI.enabled = false; 150 | EditorGUI.TextField(textPosition, Target.Build); 151 | GUI.enabled = guiEnabled; 152 | } 153 | else 154 | { 155 | Target.Build = EditorGUI.TextField(textPosition, Target.Build); 156 | } 157 | } 158 | else 159 | { 160 | Target.autoBuild = SemVerAutoBuild.Type.Manual; 161 | Target.Build = EditorGUI.TextField(position, content, Target.Build); 162 | } 163 | } 164 | 165 | private SemVer Validate() 166 | { 167 | var result = Target.Validate(); 168 | if (result.IsValid) return Target; 169 | foreach (var message in result.Errors) 170 | { 171 | EditorGUILayout.HelpBox(message, MessageType.Warning); 172 | } 173 | 174 | GUILayout.BeginHorizontal(); 175 | GUILayout.FlexibleSpace(); 176 | var fixButtonName = GUID.Generate().ToString(); 177 | GUI.SetNextControlName(fixButtonName); 178 | var isFixed = GUILayout.Button("Fix", GUILayout.Width(40)); 179 | if (isFixed) 180 | { 181 | GUI.FocusControl(fixButtonName); 182 | } 183 | 184 | GUILayout.EndHorizontal(); 185 | return isFixed ? result.Corrected : Target; 186 | } 187 | 188 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 189 | { 190 | return _position.yMax - _yMin; 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 408e18e97d3c43943a0e4d34f2ba4e06 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerTooltip.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Artees.UnitySemVer.Editor 4 | { 5 | internal static class SemVerTooltip 6 | { 7 | public const string Major = "Major"; 8 | public const string Minor = "Minor"; 9 | public const string Patch = "Patch"; 10 | public const string PreRelease = "Pre-Release"; 11 | public const string Build = "Build"; 12 | 13 | public static readonly IReadOnlyDictionary Field = new Dictionary 14 | { 15 | { 16 | Major, "Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes " + 17 | "are introduced to the public API. It MAY include minor and patch level changes. Patch and " + 18 | "minor version MUST be reset to 0 when major version is incremented." 19 | }, 20 | { 21 | Minor, "Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible " + 22 | "functionality is introduced to the public API. It MUST be incremented if any public API " + 23 | "functionality is marked as deprecated. It MAY be incremented if substantial new " + 24 | "functionality or improvements are introduced within the private code. It MAY include patch " + 25 | "level changes. Patch version MUST be reset to 0 when minor version is incremented." 26 | }, 27 | { 28 | Patch, "Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes " + 29 | "are introduced." 30 | }, 31 | { 32 | PreRelease, "A pre-release version indicates that the version is unstable and might not satisfy " + 33 | "the intended compatibility requirements as denoted by its associated normal version." 34 | }, 35 | { 36 | Build, "Build metadata MUST be ignored when determining version precedence. Thus two versions that " + 37 | "differ only in the build metadata, have the same precedence." 38 | } 39 | }; 40 | 41 | public static readonly IReadOnlyDictionary Increment = new Dictionary 42 | { 43 | { 44 | Major, "Increment the major version, reset the patch and the minor version to 0." 45 | }, 46 | { 47 | Minor, "Increment the minor version, reset the patch version to 0." 48 | }, 49 | { 50 | Patch, "Increment the patch version." 51 | } 52 | }; 53 | } 54 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Editor/SemVerTooltip.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 978d21260e8249f58a422ead3042ccf7 3 | timeCreated: 1566358941 -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Artees.UnitySemVer 5 | { 6 | /// 7 | /// A semantic version based on the Semantic Versioning 2.0.0 specification. 8 | /// 9 | [Serializable] 10 | public class SemVer : IComparable, IEquatable 11 | { 12 | public const char IdentifiersSeparator = '.'; 13 | public const char PreReleasePrefix = '-'; 14 | public const char BuildPrefix = '+'; 15 | 16 | public static bool operator ==(SemVer left, SemVer right) 17 | { 18 | return Equals(left, right); 19 | } 20 | 21 | public static bool operator !=(SemVer left, SemVer right) 22 | { 23 | return !Equals(left, right); 24 | } 25 | 26 | public static bool operator >(SemVer left, SemVer right) 27 | { 28 | return left.CompareTo(right) > 0; 29 | } 30 | 31 | public static bool operator <(SemVer left, SemVer right) 32 | { 33 | return left.CompareTo(right) < 0; 34 | } 35 | 36 | public static bool operator >=(SemVer left, SemVer right) 37 | { 38 | return left.CompareTo(right) >= 0; 39 | } 40 | 41 | public static bool operator <=(SemVer left, SemVer right) 42 | { 43 | return left.CompareTo(right) <= 0; 44 | } 45 | 46 | public static implicit operator string(SemVer s) 47 | { 48 | return s.ToString(); 49 | } 50 | 51 | public static implicit operator SemVer(string s) 52 | { 53 | return Parse(s); 54 | } 55 | 56 | public static SemVer Parse(string semVer) 57 | { 58 | return SemVerConverter.FromString(semVer); 59 | } 60 | 61 | /// 62 | /// Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced 63 | /// to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0 64 | /// when major version is incremented. 65 | /// 66 | /// 67 | public uint major; 68 | 69 | /// 70 | /// Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is 71 | /// introduced to the public API. It MUST be incremented if any public API functionality is marked as 72 | /// deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within 73 | /// the private code. It MAY include patch level changes. Patch version MUST be reset to 0 when minor version 74 | /// is incremented. 75 | /// 76 | /// 77 | public uint minor; 78 | 79 | /// 80 | /// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced. 81 | /// 82 | public uint patch; 83 | 84 | /// 85 | /// A pre-release version indicates that the version is unstable and might not satisfy the intended 86 | /// compatibility requirements as denoted by its associated normal version. 87 | /// 88 | /// 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92 89 | public string preRelease; 90 | 91 | /// 92 | /// Set the build metadata automatically 93 | /// 94 | /// 95 | public SemVerAutoBuild.Type autoBuild; 96 | 97 | [SerializeField] private string build = string.Empty; 98 | 99 | /// 100 | /// Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in 101 | /// the build metadata, have the same precedence. 102 | /// 103 | /// 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85 104 | public string Build 105 | { 106 | get => SemVerAutoBuild.Instances[autoBuild].Get(build); 107 | set => build = SemVerAutoBuild.Instances[autoBuild].Set(value); 108 | } 109 | 110 | /// 111 | /// The base part of the version number (Major.Minor.Patch). 112 | /// 113 | /// 1.9.0 114 | /// Major.Minor.Patch 115 | public string Core => $"{major}.{minor}.{patch}"; 116 | 117 | /// 118 | /// An internal version number. This number is used only to determine whether one version is more recent than 119 | /// another, with higher numbers indicating more recent versions. 120 | /// 121 | /// 122 | /// Major * 10000 + Minor * 100 + Patch 123 | public int AndroidBundleVersionCode 124 | { 125 | get 126 | { 127 | var clampedPatch = ClampAndroidBundleVersionCode(patch, "Patch"); 128 | var clampedMinor = ClampAndroidBundleVersionCode(minor, "Minor"); 129 | return (int) (major * 10000 + clampedMinor * 100 + clampedPatch); 130 | } 131 | } 132 | 133 | private static uint ClampAndroidBundleVersionCode(uint value, string name) 134 | { 135 | uint clamped; 136 | const uint max = 100; 137 | if (value >= max) 138 | { 139 | clamped = max - 1; 140 | Debug.LogWarning(name + " should be less than " + max); 141 | } 142 | else 143 | { 144 | clamped = value; 145 | } 146 | 147 | return clamped; 148 | } 149 | 150 | public SemVer() 151 | { 152 | minor = 1; 153 | preRelease = string.Empty; 154 | autoBuild = SemVerAutoBuild.Type.Manual; 155 | } 156 | 157 | /// 158 | /// Increment the major version, reset the patch and the minor version to 0. 159 | /// 160 | public void IncrementMajor() 161 | { 162 | major++; 163 | minor = patch = 0; 164 | } 165 | 166 | /// 167 | /// Increment the minor version, reset the patch version to 0. 168 | /// 169 | public void IncrementMinor() 170 | { 171 | minor++; 172 | patch = 0; 173 | } 174 | 175 | /// 176 | /// Increment the patch version. 177 | /// 178 | public void IncrementPatch() 179 | { 180 | patch++; 181 | } 182 | 183 | /// 184 | /// Check if this semantic version meets the Semantic Versioning 2.0.0 185 | /// specification. 186 | /// 187 | /// The result of validation and automatically corrected version number. 188 | public SemVerValidationResult Validate() 189 | { 190 | return new SemVerValidator().Validate(this); 191 | } 192 | 193 | /// 194 | /// Creates a copy of this semantic version. 195 | /// 196 | public SemVer Clone() 197 | { 198 | return new SemVer 199 | { 200 | major = major, 201 | minor = minor, 202 | patch = patch, 203 | preRelease = preRelease, 204 | Build = Build, 205 | autoBuild = autoBuild, 206 | }; 207 | } 208 | 209 | public int CompareTo(SemVer other) 210 | { 211 | return new SemVerComparer().Compare(this, other); 212 | } 213 | 214 | public bool Equals(SemVer other) 215 | { 216 | if (ReferenceEquals(null, other)) return false; 217 | if (ReferenceEquals(this, other)) return true; 218 | return CompareTo(other) == 0; 219 | } 220 | 221 | public override bool Equals(object obj) 222 | { 223 | if (ReferenceEquals(null, obj)) return false; 224 | if (ReferenceEquals(this, obj)) return true; 225 | return obj.GetType() == GetType() && Equals((SemVer) obj); 226 | } 227 | 228 | public override int GetHashCode() 229 | { 230 | throw new NotImplementedException(); 231 | } 232 | 233 | public override string ToString() 234 | { 235 | return SemVerConverter.ToString(this); 236 | } 237 | } 238 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b360a281c92d5084da03660bdbceda9d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Artees.UnitySemVer 4 | { 5 | /// 6 | /// Indicates that a string is a semantic version. It looks like in the Unity's Inspector. 7 | /// 8 | public class SemVerAttribute : PropertyAttribute 9 | { 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 750580d1d0c91874bbb049d58db7cef3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerAutoBuild.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Artees.UnitySemVer 5 | { 6 | /// 7 | /// Sets the build metadata automatically 8 | /// 9 | /// 10 | public abstract class SemVerAutoBuild 11 | { 12 | /// 13 | /// implementations 14 | /// 15 | public enum Type 16 | { 17 | /// 18 | /// Disables automatic build metadata 19 | /// 20 | Manual, 21 | 22 | /// 23 | /// Sets the build metadata to the 24 | /// Unity Cloud Build 25 | /// “build number” 26 | /// 27 | /// 28 | CloudBuildNumber 29 | } 30 | 31 | public static readonly IReadOnlyDictionary Instances = 32 | new Dictionary 33 | { 34 | {Type.Manual, new ManualBuild()}, 35 | {Type.CloudBuildNumber, new CloudBuildNumberBuild()} 36 | }; 37 | 38 | internal abstract string Get(string build); 39 | 40 | internal abstract string Set(string build); 41 | 42 | private class ManualBuild : SemVerAutoBuild 43 | { 44 | internal override string Get(string build) 45 | { 46 | return build; 47 | } 48 | 49 | internal override string Set(string build) 50 | { 51 | return build; 52 | } 53 | } 54 | 55 | private class CloudBuildNumberBuild : ReadOnly 56 | { 57 | internal override string Get(string build) 58 | { 59 | return CloudBuildManifest.Instance.IsLoaded 60 | ? CloudBuildManifest.Instance.BuildNumber.ToString() 61 | : string.Empty; 62 | } 63 | } 64 | 65 | public abstract class ReadOnly : SemVerAutoBuild 66 | { 67 | internal sealed override string Set(string build) 68 | { 69 | Debug.LogWarning("The build metadata is read-only"); 70 | return build; 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerAutoBuild.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1737d83daad718542a4da192d371790c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Artees.UnitySemVer 6 | { 7 | internal class SemVerComparer : IComparer 8 | { 9 | public int Compare(SemVer x, SemVer y) 10 | { 11 | if (ReferenceEquals(x, y)) return 0; 12 | if (ReferenceEquals(null, y)) return 1; 13 | if (ReferenceEquals(x, null)) return -1; 14 | var majorComparison = x.major.CompareTo(y.major); 15 | if (majorComparison != 0) return majorComparison; 16 | var minorComparison = x.minor.CompareTo(y.minor); 17 | if (minorComparison != 0) return minorComparison; 18 | var patchComparison = x.patch.CompareTo(y.patch); 19 | return patchComparison != 0 ? patchComparison : ComparePreReleaseVersions(x, y); 20 | } 21 | 22 | private static int ComparePreReleaseVersions(SemVer x, SemVer y) 23 | { 24 | if (IsPreRelease(x)) 25 | { 26 | if (!IsPreRelease(y)) return -1; 27 | } 28 | else 29 | { 30 | return IsPreRelease(y) ? 1 : 0; 31 | } 32 | 33 | var xIdentifiers = x.preRelease.Split(SemVer.IdentifiersSeparator); 34 | var yIdentifiers = y.preRelease.Split(SemVer.IdentifiersSeparator); 35 | var length = Mathf.Min(xIdentifiers.Length, yIdentifiers.Length); 36 | for (var i = 0; i < length; i++) 37 | { 38 | var xIdentifier = xIdentifiers[i]; 39 | var yIdentifier = yIdentifiers[i]; 40 | if (Equals(xIdentifier, yIdentifier)) continue; 41 | return ComparePreReleaseIdentifiers(xIdentifier, yIdentifier); 42 | } 43 | 44 | return xIdentifiers.Length.CompareTo(yIdentifiers.Length); 45 | } 46 | 47 | private static bool IsPreRelease(SemVer semVer) 48 | { 49 | return !string.IsNullOrEmpty(semVer.preRelease); 50 | } 51 | 52 | private static int ComparePreReleaseIdentifiers(string xIdentifier, string yIdentifier) 53 | { 54 | var isXNumber = int.TryParse(xIdentifier, out var xNumber); 55 | var isYNumber = int.TryParse(yIdentifier, out var yNumber); 56 | if (!isXNumber) 57 | { 58 | const StringComparison comparison = StringComparison.Ordinal; 59 | return isYNumber ? 1 : string.Compare(xIdentifier, yIdentifier, comparison); 60 | } 61 | 62 | if (isYNumber) 63 | { 64 | return xNumber.CompareTo(yNumber); 65 | } 66 | 67 | return -1; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerComparer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 597e8e731c709824ebd63ce51d89e732 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerConverter.cs: -------------------------------------------------------------------------------- 1 | namespace Artees.UnitySemVer 2 | { 3 | internal static class SemVerConverter 4 | { 5 | public static SemVer FromString(string semVerString) 6 | { 7 | var strings = semVerString.Split(SemVer.IdentifiersSeparator, SemVer.PreReleasePrefix, SemVer.BuildPrefix); 8 | var preReleaseStart = semVerString.IndexOf(SemVer.PreReleasePrefix); 9 | var buildIndex = semVerString.IndexOf(SemVer.BuildPrefix); 10 | var preReleaseEnd = buildIndex >= 0 ? buildIndex : semVerString.Length; 11 | var preRelease = preReleaseStart >= 0 12 | ? semVerString.Substring(preReleaseStart + 1, preReleaseEnd - preReleaseStart - 1) 13 | : string.Empty; 14 | var build = buildIndex >= 0 ? semVerString.Substring(buildIndex + 1) : string.Empty; 15 | uint major = 0; 16 | if (strings.Length > 0) uint.TryParse(strings[0], out major); 17 | uint minor = 1; 18 | if (strings.Length > 1) uint.TryParse(strings[1], out minor); 19 | uint patch = 0; 20 | if (strings.Length > 2) uint.TryParse(strings[2], out patch); 21 | var semVer = new SemVer 22 | { 23 | major = major, 24 | minor = minor, 25 | patch = patch, 26 | preRelease = preRelease, 27 | Build = build 28 | }; 29 | return semVer; 30 | } 31 | 32 | public static string ToString(SemVer semVer) 33 | { 34 | var preRelease = 35 | string.IsNullOrEmpty(semVer.preRelease) 36 | ? string.Empty 37 | : $"{SemVer.PreReleasePrefix}{semVer.preRelease}"; 38 | var build = 39 | string.IsNullOrEmpty(semVer.Build) 40 | ? string.Empty 41 | : $"{SemVer.BuildPrefix}{semVer.Build}"; 42 | return string.Format("{1}{0}{2}{0}{3}{4}{5}", 43 | SemVer.IdentifiersSeparator, 44 | semVer.major, 45 | semVer.minor, 46 | semVer.patch, 47 | preRelease, 48 | build); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerConverter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fac00b47af67686469d11f35ce1d162d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerErrorMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Artees.UnitySemVer 2 | { 3 | public static class SemVerErrorMessage 4 | { 5 | public const string Empty = "Pre-release and build identifiers must not be empty"; 6 | 7 | public const string Invalid = 8 | "Pre-release and build identifiers must comprise only ASCII alphanumerics and hyphen"; 9 | 10 | public const string LeadingZero = "Numeric pre-release identifiers must not include leading zeroes"; 11 | } 12 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerErrorMessage.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3f5eeb41d8aa25a48ae6727f1c6f39a2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerValidationResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | namespace Artees.UnitySemVer 4 | { 5 | /// 6 | /// Information returned about a checked semantic version. 7 | /// 8 | /// 9 | public class SemVerValidationResult 10 | { 11 | /// 12 | /// Error messages. This collection is empty if the version is valid. 13 | /// 14 | public readonly ReadOnlyCollection Errors; 15 | 16 | /// 17 | /// Automatically corrected semantic version. 18 | /// 19 | public readonly SemVer Corrected; 20 | 21 | /// 22 | /// Does the version meet the Semantic Versioning 2.0.0 specification? 23 | /// 24 | public bool IsValid => Errors.Count == 0; 25 | 26 | internal SemVerValidationResult(ReadOnlyCollection errors, SemVer corrected) 27 | { 28 | Errors = errors; 29 | Corrected = corrected; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerValidationResult.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68b57247a90d6e247bafe58100aa1ae3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace Artees.UnitySemVer 7 | { 8 | internal class SemVerValidator 9 | { 10 | private List _errors; 11 | private SemVer _corrected; 12 | 13 | public SemVerValidationResult Validate(SemVer semVer) 14 | { 15 | _errors = new List(); 16 | _corrected = semVer.Clone(); 17 | ValidatePreRelease(semVer); 18 | ValidateBuild(semVer); 19 | return new SemVerValidationResult(_errors.AsReadOnly(), _corrected.Clone()); 20 | } 21 | 22 | private void ValidatePreRelease(SemVer semVer) 23 | { 24 | var identifiers = ValidateIdentifiers(semVer.preRelease); 25 | identifiers = ValidateLeadingZeroes(identifiers); 26 | var joined = JoinIdentifiers(identifiers); 27 | _corrected.preRelease = joined; 28 | } 29 | 30 | private void ValidateBuild(SemVer semVer) 31 | { 32 | if (SemVerAutoBuild.Instances[semVer.autoBuild] is SemVerAutoBuild.ReadOnly) return; 33 | var identifiers = ValidateIdentifiers(semVer.Build); 34 | var joined = JoinIdentifiers(identifiers); 35 | _corrected.Build = joined; 36 | } 37 | 38 | private string[] ValidateIdentifiers(string identifiers) 39 | { 40 | if (string.IsNullOrEmpty(identifiers)) return new string[0]; 41 | var separators = new[] {SemVer.IdentifiersSeparator}; 42 | var strings = identifiers.Split(separators, StringSplitOptions.RemoveEmptyEntries); 43 | if (strings.Length < identifiers.Count(c => c == SemVer.IdentifiersSeparator) + 1) 44 | { 45 | _errors.Add(SemVerErrorMessage.Empty); 46 | } 47 | 48 | for (var i = 0; i < strings.Length; i++) 49 | { 50 | var raw = strings[i]; 51 | var corrected = Regex.Replace(raw, "[^0-9A-Za-z-]", "-"); 52 | if (string.Equals(raw, corrected)) continue; 53 | _errors.Add(SemVerErrorMessage.Invalid); 54 | strings[i] = corrected; 55 | } 56 | 57 | return strings; 58 | } 59 | 60 | private string[] ValidateLeadingZeroes(IList identifiers) 61 | { 62 | var length = identifiers.Count; 63 | var corrected = new string[length]; 64 | for (var i = 0; i < length; i++) 65 | { 66 | var identifier = identifiers[i]; 67 | var isNumeric = int.TryParse(identifier, out var numericIdentifier); 68 | if (isNumeric && identifier.StartsWith("0") && identifier.Length > 1) 69 | { 70 | corrected[i] = numericIdentifier.ToString(); 71 | _errors.Add(SemVerErrorMessage.LeadingZero); 72 | } 73 | else 74 | { 75 | corrected[i] = identifier; 76 | } 77 | } 78 | 79 | return corrected; 80 | } 81 | 82 | private static string JoinIdentifiers(string[] identifiers) 83 | { 84 | return string.Join(SemVer.IdentifiersSeparator.ToString(), identifiers); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/SemVerValidator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e4d13e62ac847645b7918beff4e7beb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a805427e19730d4091f5994a9621e54 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/Artees.UnitySemVer.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Artees.UnitySemVer.Tests", 3 | "references": [ 4 | "GUID:c7f2f2911de381941be7186214305448", 5 | "GUID:27619889b8ba8c24980f49ee34dbb44a", 6 | "GUID:0acc523941302664db1f4e527237feb3" 7 | ], 8 | "includePlatforms": [ 9 | "Editor" 10 | ], 11 | "excludePlatforms": [], 12 | "allowUnsafeCode": false, 13 | "overrideReferences": true, 14 | "precompiledReferences": [ 15 | "nunit.framework.dll" 16 | ], 17 | "autoReferenced": false, 18 | "defineConstraints": [ 19 | "UNITY_INCLUDE_TESTS" 20 | ], 21 | "versionDefines": [], 22 | "noEngineReferences": false 23 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/Artees.UnitySemVer.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e22d7af35ad796d4b840b615c5d56ea2 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/SemVerTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Linq; 5 | using NUnit.Framework; 6 | using NUnit.Framework.Constraints; 7 | 8 | namespace Artees.UnitySemVer.Tests 9 | { 10 | [TestFixture] 11 | internal class SemVerTests 12 | { 13 | [TestCaseSource(typeof(Data), nameof(Data.ValidVersionsTestCases))] 14 | public void MajorMinorPatchTest(SemVer semVer) 15 | { 16 | Assert.That(semVer.major, Is.Not.Negative); 17 | Assert.That(semVer.minor, Is.Not.Negative); 18 | Assert.That(semVer.patch, Is.Not.Negative); 19 | } 20 | 21 | [TestCaseSource(typeof(Data), nameof(Data.ValidVersionsTestCases))] 22 | public void PreReleaseTest(SemVer semVer) 23 | { 24 | foreach (var identifier in semVer.preRelease.Split('.')) 25 | { 26 | Assert.That(identifier, Is.Empty.Or.Match("[0-9A-Za-z-]")); 27 | int.TryParse(identifier, out var numericIdentifier); 28 | if (numericIdentifier > 0) 29 | { 30 | Assert.That(identifier, Does.Not.StartsWith("0")); 31 | } 32 | } 33 | } 34 | 35 | [TestCaseSource(typeof(Data), nameof(Data.ValidVersionsTestCases))] 36 | public void BuildTest(SemVer semVer) 37 | { 38 | foreach (var identifier in semVer.Build.Split('.')) 39 | { 40 | Assert.That(identifier, Is.Empty.Or.Match("[0-9A-Za-z-]")); 41 | } 42 | } 43 | 44 | [TestCaseSource(typeof(Data), nameof(Data.ValidateTestCases))] 45 | public ReadOnlyCollection ValidateTest(SemVer invalid, SemVer corrected) 46 | { 47 | var original = invalid.Clone(); 48 | var result = invalid.Validate(); 49 | EqualsTest(original, invalid); 50 | EqualsTest(result.Corrected, corrected); 51 | MajorMinorPatchTest(result.Corrected); 52 | PreReleaseTest(result.Corrected); 53 | BuildTest(result.Corrected); 54 | var expression = result.IsValid ? new ConstraintExpression() : Does.Not; 55 | Assert.That(original.ToString(), expression.Match(SuggestedRegEx.Pattern)); 56 | Assert.That(result.Corrected.ToString(), Does.Match(SuggestedRegEx.Pattern)); 57 | return result.Errors; 58 | } 59 | 60 | [TestCaseSource(typeof(Data), nameof(Data.EqualsTestCases))] 61 | public void EqualsTest(SemVer left, SemVer right) 62 | { 63 | Assert.That(left, Is.EqualTo(right)); 64 | } 65 | 66 | [TestCaseSource(typeof(Data), nameof(Data.NotEqualTestCases))] 67 | public void NotEqualTest(SemVer left, SemVer right) 68 | { 69 | Assert.That(left, Is.Not.EqualTo(right)); 70 | } 71 | 72 | [TestCaseSource(typeof(Data), nameof(Data.CompareTestCases))] 73 | public void CompareTest(SemVer big, SemVer small) 74 | { 75 | Assert.That(big, Is.GreaterThan(small)); 76 | Assert.That(small, Is.LessThan(big)); 77 | } 78 | 79 | [TestCaseSource(typeof(Data), nameof(Data.ConvertToStringTestCases))] 80 | public string ConvertToStringTest(SemVer semVer) 81 | { 82 | return semVer; 83 | } 84 | 85 | [TestCaseSource(typeof(Data), nameof(Data.ConvertFromStringTestCases))] 86 | public SemVer ConvertFromStringTest(string semVer) 87 | { 88 | return semVer; 89 | } 90 | 91 | [TestCaseSource(typeof(Data), nameof(Data.AutoBuildTestCases))] 92 | public string AutoBuildTest(SemVer semVer) 93 | { 94 | Assert.That(SemVerAutoBuild.Instances.Keys, Does.Contain(semVer.autoBuild)); 95 | return semVer.Build; 96 | } 97 | 98 | [TestCaseSource(typeof(Data), nameof(Data.CoreTestCases))] 99 | public string CoreTest(SemVer semVer) 100 | { 101 | return semVer.Core; 102 | } 103 | 104 | [TestCaseSource(typeof(Data), nameof(Data.AndroidBundleVersionCode))] 105 | public int AndroidBundleVersionCodeTest(SemVer semVer) 106 | { 107 | return semVer.AndroidBundleVersionCode; 108 | } 109 | 110 | [SuppressMessage("ReSharper", "UnusedMember.Local")] 111 | private class Data 112 | { 113 | private static IEnumerable ValidVersions 114 | { 115 | get 116 | { 117 | yield return new SemVer(); 118 | yield return new SemVer 119 | { 120 | major = 1, 121 | minor = 2, 122 | patch = 3 123 | }; 124 | yield return new SemVer 125 | { 126 | major = 1, 127 | minor = 2, 128 | patch = 3, 129 | preRelease = "alpha" 130 | }; 131 | yield return new SemVer 132 | { 133 | major = 1, 134 | minor = 2, 135 | patch = 3, 136 | preRelease = "alpha", 137 | Build = "CustomBuild1" 138 | }; 139 | yield return new SemVer 140 | { 141 | major = 1, 142 | minor = 2, 143 | patch = 3, 144 | preRelease = "alpha", 145 | Build = "CustomBuild2" 146 | }; 147 | yield return new SemVer 148 | { 149 | preRelease = "ALPHA" 150 | }; 151 | yield return new SemVer 152 | { 153 | preRelease = "alpha.1" 154 | }; 155 | yield return new SemVer 156 | { 157 | preRelease = "0.3.7", 158 | Build = "20130313144700" 159 | }; 160 | yield return new SemVer 161 | { 162 | preRelease = "x.7.z.92", 163 | Build = "exp.sha.5114f85" 164 | }; 165 | yield return new SemVer 166 | { 167 | major = 1, 168 | minor = 0, 169 | patch = 0, 170 | preRelease = "alpha", 171 | Build = "001" 172 | }; 173 | } 174 | } 175 | 176 | public static IEnumerable ValidVersionsTestCases 177 | { 178 | get { return ValidVersions.Select(semVer => new TestCaseData(semVer)); } 179 | } 180 | 181 | public static IEnumerable ValidateTestCases 182 | { 183 | get 184 | { 185 | yield return new TestCaseData(new SemVer 186 | { 187 | preRelease = ".", 188 | Build = "." 189 | }, new SemVer()).Returns(new[] 190 | { 191 | SemVerErrorMessage.Empty, 192 | SemVerErrorMessage.Empty 193 | }); 194 | yield return new TestCaseData(new SemVer 195 | { 196 | preRelease = "a..a", 197 | Build = "a..a" 198 | }, new SemVer 199 | { 200 | preRelease = "a.a", 201 | Build = "a.a" 202 | }).Returns(new[] 203 | { 204 | SemVerErrorMessage.Empty, 205 | SemVerErrorMessage.Empty 206 | }); 207 | yield return new TestCaseData(new SemVer 208 | { 209 | preRelease = "a a", 210 | Build = "a a" 211 | }, new SemVer 212 | { 213 | preRelease = "a-a", 214 | Build = "a-a" 215 | }).Returns(new[] 216 | { 217 | SemVerErrorMessage.Invalid, 218 | SemVerErrorMessage.Invalid 219 | }); 220 | yield return new TestCaseData(new SemVer 221 | { 222 | preRelease = "$", 223 | Build = "$" 224 | }, new SemVer 225 | { 226 | preRelease = "-", 227 | Build = "-" 228 | }).Returns(new[] 229 | { 230 | SemVerErrorMessage.Invalid, 231 | SemVerErrorMessage.Invalid 232 | }); 233 | yield return new TestCaseData(new SemVer 234 | { 235 | preRelease = "01" 236 | }, new SemVer 237 | { 238 | preRelease = "1" 239 | }).Returns(new[] 240 | { 241 | SemVerErrorMessage.LeadingZero 242 | }); 243 | } 244 | } 245 | 246 | public static IEnumerable EqualsTestCases 247 | { 248 | get 249 | { 250 | foreach (var semVer in ValidVersions) 251 | { 252 | yield return new TestCaseData(semVer, semVer.Clone()); 253 | } 254 | 255 | yield return new TestCaseData( 256 | new SemVer 257 | { 258 | major = 1, 259 | minor = 7, 260 | patch = 3, 261 | preRelease = "alpha", 262 | Build = "001" 263 | }, 264 | new SemVer 265 | { 266 | major = 1, 267 | minor = 7, 268 | patch = 3, 269 | preRelease = "alpha", 270 | Build = "2" 271 | }); 272 | } 273 | } 274 | 275 | public static IEnumerable NotEqualTestCases 276 | { 277 | get 278 | { 279 | foreach (var semVer in ValidVersions) 280 | { 281 | var other = semVer.Clone(); 282 | other.IncrementMajor(); 283 | yield return new TestCaseData(semVer, other); 284 | } 285 | } 286 | } 287 | 288 | public static IEnumerable CompareTestCases 289 | { 290 | get 291 | { 292 | yield return new TestCaseData( 293 | new SemVer 294 | { 295 | major = 2, 296 | minor = 1, 297 | patch = 1 298 | }, 299 | new SemVer 300 | { 301 | major = 2, 302 | minor = 1, 303 | patch = 0 304 | }); 305 | yield return new TestCaseData( 306 | new SemVer 307 | { 308 | major = 2, 309 | minor = 1, 310 | patch = 0 311 | }, 312 | new SemVer 313 | { 314 | major = 2, 315 | minor = 0, 316 | patch = 0 317 | }); 318 | yield return new TestCaseData( 319 | new SemVer 320 | { 321 | major = 2, 322 | minor = 0, 323 | patch = 0 324 | }, 325 | new SemVer 326 | { 327 | major = 1, 328 | minor = 0, 329 | patch = 0 330 | }); 331 | yield return new TestCaseData( 332 | new SemVer 333 | { 334 | major = 1, 335 | minor = 7, 336 | patch = 3, 337 | preRelease = string.Empty 338 | }, 339 | new SemVer 340 | { 341 | major = 1, 342 | minor = 7, 343 | patch = 3, 344 | preRelease = "alpha" 345 | }); 346 | yield return new TestCaseData( 347 | new SemVer 348 | { 349 | major = 1, 350 | minor = 0, 351 | patch = 0 352 | }, 353 | new SemVer 354 | { 355 | major = 1, 356 | minor = 0, 357 | patch = 0, 358 | preRelease = "rc.1" 359 | }); 360 | yield return new TestCaseData( 361 | new SemVer 362 | { 363 | major = 1, 364 | minor = 0, 365 | patch = 0, 366 | preRelease = "rc.1" 367 | }, 368 | new SemVer 369 | { 370 | major = 1, 371 | minor = 0, 372 | patch = 0, 373 | preRelease = "beta.11" 374 | }); 375 | yield return new TestCaseData( 376 | new SemVer 377 | { 378 | major = 1, 379 | minor = 0, 380 | patch = 0, 381 | preRelease = "beta.11" 382 | }, 383 | new SemVer 384 | { 385 | major = 1, 386 | minor = 0, 387 | patch = 0, 388 | preRelease = "beta.2" 389 | }); 390 | yield return new TestCaseData( 391 | new SemVer 392 | { 393 | major = 1, 394 | minor = 0, 395 | patch = 0, 396 | preRelease = "beta.2" 397 | }, 398 | new SemVer 399 | { 400 | major = 1, 401 | minor = 0, 402 | patch = 0, 403 | preRelease = "beta" 404 | }); 405 | yield return new TestCaseData( 406 | new SemVer 407 | { 408 | major = 1, 409 | minor = 0, 410 | patch = 0, 411 | preRelease = "beta" 412 | }, 413 | new SemVer 414 | { 415 | major = 1, 416 | minor = 0, 417 | patch = 0, 418 | preRelease = "alpha.beta" 419 | }); 420 | yield return new TestCaseData( 421 | new SemVer 422 | { 423 | major = 1, 424 | minor = 0, 425 | patch = 0, 426 | preRelease = "alpha.beta" 427 | }, 428 | new SemVer 429 | { 430 | major = 1, 431 | minor = 0, 432 | patch = 0, 433 | preRelease = "alpha.1" 434 | }); 435 | yield return new TestCaseData( 436 | new SemVer 437 | { 438 | major = 1, 439 | minor = 0, 440 | patch = 0, 441 | preRelease = "alpha.1" 442 | }, 443 | new SemVer 444 | { 445 | major = 1, 446 | minor = 0, 447 | patch = 0, 448 | preRelease = "alpha" 449 | }); 450 | } 451 | } 452 | 453 | public static IEnumerable ConvertToStringTestCases 454 | { 455 | get 456 | { 457 | yield return new TestCaseData(new SemVer 458 | { 459 | major = 1, 460 | minor = 2, 461 | patch = 3, 462 | preRelease = "pr", 463 | Build = "b" 464 | }).Returns("1.2.3-pr+b"); 465 | yield return new TestCaseData(new SemVer 466 | { 467 | preRelease = "pre-alpha" 468 | }).Returns("0.1.0-pre-alpha"); 469 | } 470 | } 471 | 472 | public static IEnumerable ConvertFromStringTestCases 473 | { 474 | get 475 | { 476 | yield return new TestCaseData("1.2.3-pr+b").Returns(new SemVer 477 | { 478 | major = 1, 479 | minor = 2, 480 | patch = 3, 481 | preRelease = "pr", 482 | Build = "b" 483 | }); 484 | yield return new TestCaseData("1.2.3+b").Returns(new SemVer 485 | { 486 | major = 1, 487 | minor = 2, 488 | patch = 3, 489 | Build = "b" 490 | }); 491 | yield return new TestCaseData("1.2.3-pr").Returns(new SemVer 492 | { 493 | major = 1, 494 | minor = 2, 495 | patch = 3, 496 | preRelease = "pr" 497 | }); 498 | yield return new TestCaseData("0.1.0-pre-alpha").Returns(new SemVer 499 | { 500 | preRelease = "pre-alpha" 501 | }); 502 | } 503 | } 504 | 505 | public static IEnumerable AutoBuildTestCases 506 | { 507 | get 508 | { 509 | yield return new TestCaseData(new SemVer 510 | { 511 | autoBuild = SemVerAutoBuild.Type.Manual, 512 | Build = "auto-build" 513 | }).Returns("auto-build"); 514 | } 515 | } 516 | 517 | public static IEnumerable CoreTestCases 518 | { 519 | get 520 | { 521 | yield return new TestCaseData(new SemVer 522 | { 523 | major = 4, 524 | minor = 5, 525 | patch = 6, 526 | preRelease = "alpha", 527 | Build = "CustomBuild3" 528 | }).Returns("4.5.6"); 529 | } 530 | } 531 | 532 | public static IEnumerable AndroidBundleVersionCode 533 | { 534 | get 535 | { 536 | yield return new TestCaseData(new SemVer 537 | { 538 | major = 1, 539 | minor = 2, 540 | patch = 3, 541 | preRelease = "alpha", 542 | Build = "CustomBuild4" 543 | }).Returns(10203); 544 | } 545 | } 546 | } 547 | } 548 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/SemVerTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2264000e44e2c8b439f2b4d65771c655 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/SuggestedRegEx.cs: -------------------------------------------------------------------------------- 1 | namespace Artees.UnitySemVer.Tests 2 | { 3 | internal static class SuggestedRegEx 4 | { 5 | /// 6 | /// This is one of the 7 | /// 8 | /// suggested regular expressions to check a SemVer string. 9 | /// 10 | public const string Pattern = @"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"; 11 | } 12 | } -------------------------------------------------------------------------------- /Artees/UnitySemVer/Tests/SuggestedRegEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54e2d67644ed4c588ab934b2cbfa0626 3 | timeCreated: 1566353659 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Artees 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d14b07ec6520d145b858a7d6ac12e81 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity SemVer 2 | [![openupm](https://img.shields.io/npm/v/games.artees.semver?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/games.artees.semver/) 3 | 4 | A convenient way to edit and compare version numbers according to the [Semantic Versioning 2.0.0](https://semver.org/) specification. Also includes a property drawer for Unity. 5 | 6 | ![Property drawer](https://github.com/Artees/Unity-SemVer/raw/master/SemVerDrawer.png) 7 | 8 | # Installation 9 | Install the package **games.artees.semver** using [my package registry](https://artees.games/upm). 10 | Or install via the [OpenUPM registry](https://openupm.com/packages/games.artees.semver/). 11 | 12 | # Usage 13 | Use the `Artees.UnitySemVer.SemVer` class or apply the `Artees.UnitySemVer.SemVerAttribute` attribute to a string field. 14 | ``` 15 | public SemVer version = new SemVer {major = 1, minor = 2, patch = 3}; 16 | [SemVer] public string versionString = "1.2.3"; 17 | ``` 18 | 19 | Parsing: 20 | ``` 21 | var version = SemVer.Parse("2.0.0-rc.1+build.123"); 22 | ``` 23 | 24 | Comparing: 25 | ``` 26 | Debug.Log("2.1.0" > version); 27 | ``` 28 | 29 | Validating: 30 | ``` 31 | var result = version.Validate(); 32 | version = result.Corrected; 33 | foreach (var message in result.Errors) 34 | { 35 | Debug.LogWarning(message); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93254f5acd8cea149802724277ab6b03 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e54b222327cdfd4d8602629755ae5ea 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scenes/SampleScene.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 705507994} 41 | m_IndirectSpecularColor: {r: 0.4465782, g: 0.49641252, b: 0.5748167, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 12 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_AtlasSize: 1024 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 1 64 | m_CompAOExponentDirect: 0 65 | m_ExtractAmbientOcclusion: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVREnvironmentSampleCount: 500 81 | m_PVREnvironmentReferencePointCount: 2048 82 | m_PVRFilteringMode: 2 83 | m_PVRDenoiserTypeDirect: 0 84 | m_PVRDenoiserTypeIndirect: 0 85 | m_PVRDenoiserTypeAO: 0 86 | m_PVRFilterTypeDirect: 0 87 | m_PVRFilterTypeIndirect: 0 88 | m_PVRFilterTypeAO: 0 89 | m_PVREnvironmentMIS: 0 90 | m_PVRCulling: 1 91 | m_PVRFilteringGaussRadiusDirect: 1 92 | m_PVRFilteringGaussRadiusIndirect: 5 93 | m_PVRFilteringGaussRadiusAO: 2 94 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 95 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 96 | m_PVRFilteringAtrousPositionSigmaAO: 1 97 | m_ExportTrainingData: 0 98 | m_TrainingDataDestination: TrainingData 99 | m_LightingDataAsset: {fileID: 0} 100 | m_UseShadowmask: 1 101 | --- !u!196 &4 102 | NavMeshSettings: 103 | serializedVersion: 2 104 | m_ObjectHideFlags: 0 105 | m_BuildSettings: 106 | serializedVersion: 2 107 | agentTypeID: 0 108 | agentRadius: 0.5 109 | agentHeight: 2 110 | agentSlope: 45 111 | agentClimb: 0.4 112 | ledgeDropHeight: 0 113 | maxJumpAcrossDistance: 0 114 | minRegionArea: 2 115 | manualCellSize: 0 116 | cellSize: 0.16666667 117 | manualTileSize: 0 118 | tileSize: 256 119 | accuratePlacement: 0 120 | debug: 121 | m_Flags: 0 122 | m_NavMeshData: {fileID: 0} 123 | --- !u!1 &705507993 124 | GameObject: 125 | m_ObjectHideFlags: 0 126 | m_CorrespondingSourceObject: {fileID: 0} 127 | m_PrefabInstance: {fileID: 0} 128 | m_PrefabAsset: {fileID: 0} 129 | serializedVersion: 6 130 | m_Component: 131 | - component: {fileID: 705507995} 132 | - component: {fileID: 705507994} 133 | m_Layer: 0 134 | m_Name: Directional Light 135 | m_TagString: Untagged 136 | m_Icon: {fileID: 0} 137 | m_NavMeshLayer: 0 138 | m_StaticEditorFlags: 0 139 | m_IsActive: 1 140 | --- !u!108 &705507994 141 | Light: 142 | m_ObjectHideFlags: 0 143 | m_CorrespondingSourceObject: {fileID: 0} 144 | m_PrefabInstance: {fileID: 0} 145 | m_PrefabAsset: {fileID: 0} 146 | m_GameObject: {fileID: 705507993} 147 | m_Enabled: 1 148 | serializedVersion: 9 149 | m_Type: 1 150 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 151 | m_Intensity: 1 152 | m_Range: 10 153 | m_SpotAngle: 30 154 | m_InnerSpotAngle: 21.80208 155 | m_CookieSize: 10 156 | m_Shadows: 157 | m_Type: 2 158 | m_Resolution: -1 159 | m_CustomResolution: -1 160 | m_Strength: 1 161 | m_Bias: 0.05 162 | m_NormalBias: 0.4 163 | m_NearPlane: 0.2 164 | m_CullingMatrixOverride: 165 | e00: 1 166 | e01: 0 167 | e02: 0 168 | e03: 0 169 | e10: 0 170 | e11: 1 171 | e12: 0 172 | e13: 0 173 | e20: 0 174 | e21: 0 175 | e22: 1 176 | e23: 0 177 | e30: 0 178 | e31: 0 179 | e32: 0 180 | e33: 1 181 | m_UseCullingMatrixOverride: 0 182 | m_Cookie: {fileID: 0} 183 | m_DrawHalo: 0 184 | m_Flare: {fileID: 0} 185 | m_RenderMode: 0 186 | m_CullingMask: 187 | serializedVersion: 2 188 | m_Bits: 4294967295 189 | m_RenderingLayerMask: 1 190 | m_Lightmapping: 1 191 | m_LightShadowCasterMode: 0 192 | m_AreaSize: {x: 1, y: 1} 193 | m_BounceIntensity: 1 194 | m_ColorTemperature: 6570 195 | m_UseColorTemperature: 0 196 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 197 | m_UseBoundingSphereOverride: 0 198 | m_ShadowRadius: 0 199 | m_ShadowAngle: 0 200 | --- !u!4 &705507995 201 | Transform: 202 | m_ObjectHideFlags: 0 203 | m_CorrespondingSourceObject: {fileID: 0} 204 | m_PrefabInstance: {fileID: 0} 205 | m_PrefabAsset: {fileID: 0} 206 | m_GameObject: {fileID: 705507993} 207 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 208 | m_LocalPosition: {x: 0, y: 3, z: 0} 209 | m_LocalScale: {x: 1, y: 1, z: 1} 210 | m_Children: [] 211 | m_Father: {fileID: 0} 212 | m_RootOrder: 1 213 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 214 | --- !u!1 &963194225 215 | GameObject: 216 | m_ObjectHideFlags: 0 217 | m_CorrespondingSourceObject: {fileID: 0} 218 | m_PrefabInstance: {fileID: 0} 219 | m_PrefabAsset: {fileID: 0} 220 | serializedVersion: 6 221 | m_Component: 222 | - component: {fileID: 963194228} 223 | - component: {fileID: 963194227} 224 | - component: {fileID: 963194226} 225 | m_Layer: 0 226 | m_Name: Main Camera 227 | m_TagString: MainCamera 228 | m_Icon: {fileID: 0} 229 | m_NavMeshLayer: 0 230 | m_StaticEditorFlags: 0 231 | m_IsActive: 1 232 | --- !u!81 &963194226 233 | AudioListener: 234 | m_ObjectHideFlags: 0 235 | m_CorrespondingSourceObject: {fileID: 0} 236 | m_PrefabInstance: {fileID: 0} 237 | m_PrefabAsset: {fileID: 0} 238 | m_GameObject: {fileID: 963194225} 239 | m_Enabled: 1 240 | --- !u!20 &963194227 241 | Camera: 242 | m_ObjectHideFlags: 0 243 | m_CorrespondingSourceObject: {fileID: 0} 244 | m_PrefabInstance: {fileID: 0} 245 | m_PrefabAsset: {fileID: 0} 246 | m_GameObject: {fileID: 963194225} 247 | m_Enabled: 1 248 | serializedVersion: 2 249 | m_ClearFlags: 1 250 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 251 | m_projectionMatrixMode: 1 252 | m_GateFitMode: 2 253 | m_FOVAxisMode: 0 254 | m_SensorSize: {x: 36, y: 24} 255 | m_LensShift: {x: 0, y: 0} 256 | m_FocalLength: 50 257 | m_NormalizedViewPortRect: 258 | serializedVersion: 2 259 | x: 0 260 | y: 0 261 | width: 1 262 | height: 1 263 | near clip plane: 0.3 264 | far clip plane: 1000 265 | field of view: 60 266 | orthographic: 0 267 | orthographic size: 5 268 | m_Depth: -1 269 | m_CullingMask: 270 | serializedVersion: 2 271 | m_Bits: 4294967295 272 | m_RenderingPath: -1 273 | m_TargetTexture: {fileID: 0} 274 | m_TargetDisplay: 0 275 | m_TargetEye: 3 276 | m_HDR: 1 277 | m_AllowMSAA: 1 278 | m_AllowDynamicResolution: 0 279 | m_ForceIntoRT: 0 280 | m_OcclusionCulling: 1 281 | m_StereoConvergence: 10 282 | m_StereoSeparation: 0.022 283 | --- !u!4 &963194228 284 | Transform: 285 | m_ObjectHideFlags: 0 286 | m_CorrespondingSourceObject: {fileID: 0} 287 | m_PrefabInstance: {fileID: 0} 288 | m_PrefabAsset: {fileID: 0} 289 | m_GameObject: {fileID: 963194225} 290 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 291 | m_LocalPosition: {x: 0, y: 1, z: -10} 292 | m_LocalScale: {x: 1, y: 1, z: 1} 293 | m_Children: [] 294 | m_Father: {fileID: 0} 295 | m_RootOrder: 0 296 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 297 | --- !u!1 &1417300875 298 | GameObject: 299 | m_ObjectHideFlags: 0 300 | m_CorrespondingSourceObject: {fileID: 0} 301 | m_PrefabInstance: {fileID: 0} 302 | m_PrefabAsset: {fileID: 0} 303 | serializedVersion: 6 304 | m_Component: 305 | - component: {fileID: 1417300877} 306 | - component: {fileID: 1417300876} 307 | m_Layer: 0 308 | m_Name: SemVerDrawerTest 309 | m_TagString: Untagged 310 | m_Icon: {fileID: 0} 311 | m_NavMeshLayer: 0 312 | m_StaticEditorFlags: 0 313 | m_IsActive: 1 314 | --- !u!114 &1417300876 315 | MonoBehaviour: 316 | m_ObjectHideFlags: 0 317 | m_CorrespondingSourceObject: {fileID: 0} 318 | m_PrefabInstance: {fileID: 0} 319 | m_PrefabAsset: {fileID: 0} 320 | m_GameObject: {fileID: 1417300875} 321 | m_Enabled: 1 322 | m_EditorHideFlags: 0 323 | m_Script: {fileID: 11500000, guid: 6664d7d4013f5ab4f872ce0211cdfa9e, type: 3} 324 | m_Name: 325 | m_EditorClassIdentifier: 326 | version: 327 | major: 0 328 | minor: 2 329 | patch: 1 330 | preRelease: alpha 331 | autoBuild: 1 332 | build: 333 | versionString: 0.3.2-beta+build 334 | --- !u!4 &1417300877 335 | Transform: 336 | m_ObjectHideFlags: 0 337 | m_CorrespondingSourceObject: {fileID: 0} 338 | m_PrefabInstance: {fileID: 0} 339 | m_PrefabAsset: {fileID: 0} 340 | m_GameObject: {fileID: 1417300875} 341 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 342 | m_LocalPosition: {x: 0, y: 0, z: 0} 343 | m_LocalScale: {x: 1, y: 1, z: 1} 344 | m_Children: [] 345 | m_Father: {fileID: 0} 346 | m_RootOrder: 2 347 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 348 | -------------------------------------------------------------------------------- /Scenes/SampleScene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9fc0d4010bbf28b4594072e72b8655ab 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f0b33bee91b86149b268a5bb2cc3c0b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/SemVerDrawerTest.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Artees.UnitySemVer; 3 | using UnityEngine; 4 | 5 | [SuppressMessage("ReSharper", "NotAccessedField.Local")] 6 | public class SemVerDrawerTest : MonoBehaviour 7 | { 8 | [SerializeField] private SemVer version; 9 | [SerializeField, SemVer] private string versionString; 10 | } 11 | -------------------------------------------------------------------------------- /Scripts/SemVerDrawerTest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6664d7d4013f5ab4f872ce0211cdfa9e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /SemVerDrawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Artees/Unity-SemVer/5101c136a696c450ce0174710f875d634610d63b/SemVerDrawer.png -------------------------------------------------------------------------------- /SemVerDrawer.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6a8899fab14951342b4d2df95ea1fed8 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 10 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 3 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | forceMaximumCompressionQuality_BC6H_BC7: 0 73 | spriteSheet: 74 | serializedVersion: 2 75 | sprites: [] 76 | outline: [] 77 | physicsShape: [] 78 | bones: [] 79 | spriteID: 80 | internalID: 0 81 | vertices: [] 82 | indices: 83 | edges: [] 84 | weights: [] 85 | secondaryTextures: [] 86 | spritePackingTag: 87 | pSDRemoveMatte: 0 88 | pSDShowRemoveMatteOption: 0 89 | userData: 90 | assetBundleName: 91 | assetBundleVariant: 92 | -------------------------------------------------------------------------------- /UnityCloud.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d428cb2052238b41aae3329caf87389 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityCloud/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0dcfa1b8998a5140a6a222d06220019 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityCloud/Resources/TestUnityCloudBuildManifest.json.txt: -------------------------------------------------------------------------------- 1 | { 2 | "buildNumber": "1" 3 | } -------------------------------------------------------------------------------- /UnityCloud/Resources/TestUnityCloudBuildManifest.json.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0933e7327b5886a49b3a75f91dbd4e52 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "games.artees.semver", 3 | "version": "0.3.5", 4 | "displayName": "Unity SemVer", 5 | "description": "A convenient way to edit and compare version numbers according to the Semantic Versioning 2.0.0 specification. Also includes a property drawer for Unity.", 6 | "unity": "2019.4", 7 | "unityRelease": "", 8 | "dependencies": { 9 | "com.unity.test-framework": "1.1.20" 10 | }, 11 | "keywords": [], 12 | "author": { 13 | "name": "Artees", 14 | "email": "yo@artees.games", 15 | "url": "https://github.com/Artees/Unity-SemVer" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6701f03f2ec10842b4f7b4eff5fab35 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------