├── .gitignore ├── ApplicationVersion.cs ├── ApplicationVersion.cs.meta ├── ApplicationVersion.png ├── ApplicationVersion.png.meta ├── Artees.ApplicationVersion.asmdef ├── Artees.ApplicationVersion.asmdef.meta ├── Editor.meta ├── Editor ├── ApplicationVersionBuildPreprocessor.cs ├── ApplicationVersionBuildPreprocessor.cs.meta ├── ApplicationVersionEditor.cs ├── ApplicationVersionEditor.cs.meta ├── Artees.ApplicationVersion.Editor.asmdef └── Artees.ApplicationVersion.Editor.asmdef.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.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 | 39 | *.jsonpackage 40 | *.jsonpackage.meta 41 | -------------------------------------------------------------------------------- /ApplicationVersion.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Artees.UnitySemVer; 3 | using UnityEngine; 4 | 5 | namespace Artees.AppVersion 6 | { 7 | [CreateAssetMenu(menuName = "Artees/Application Version")] 8 | public class ApplicationVersion : ScriptableObject 9 | { 10 | [SerializeField] private SemVer version; 11 | [SerializeField] private bool applyOnBuild = true; 12 | 13 | [SuppressMessage("ReSharper", "ConvertToAutoPropertyWithPrivateSetter", 14 | Justification = "Serializable")] 15 | public SemVer Version => version; 16 | 17 | [SuppressMessage("ReSharper", "ConvertToAutoProperty", Justification = "Serializable")] 18 | public bool ApplyOnBuild => applyOnBuild; 19 | 20 | private void Awake() 21 | { 22 | if (version != null && 23 | (version.autoBuild != SemVerAutoBuild.Type.Manual || version != new SemVer())) return; 24 | version = SemVer.Parse(Application.version); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /ApplicationVersion.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2fbfc580a21381343b0eb0e6f10845bc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /ApplicationVersion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Artees/Unity-Application-Version/25bbb752d0ea0a9e4d3c93c31a5e14504159db87/ApplicationVersion.png -------------------------------------------------------------------------------- /ApplicationVersion.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36897ab14a1314d42a8e1c314d930dd3 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 | -------------------------------------------------------------------------------- /Artees.ApplicationVersion.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Artees.ApplicationVersion", 3 | "references": [ 4 | "GUID:c7f2f2911de381941be7186214305448" 5 | ], 6 | "includePlatforms": [], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": false, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [] 14 | } -------------------------------------------------------------------------------- /Artees.ApplicationVersion.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c3f1380e574b164a89bcd1cbdf7b747 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b4ed51164750584d8108a2d80eb6739 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/ApplicationVersionBuildPreprocessor.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Linq; 3 | using UnityEditor.Build; 4 | using UnityEditor.Build.Reporting; 5 | using UnityEngine; 6 | 7 | namespace Artees.AppVersion.Editor 8 | { 9 | [SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Build Preprocessor")] 10 | public class ApplicationVersionBuildPreprocessor : IPreprocessBuildWithReport 11 | { 12 | public int callbackOrder => 0; 13 | 14 | public void OnPreprocessBuild(BuildReport report) 15 | { 16 | foreach (var av in Resources.LoadAll("").Where(av => av.ApplyOnBuild)) 17 | { 18 | ApplicationVersionEditor.Apply(av.Version); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Editor/ApplicationVersionBuildPreprocessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b268f94492cd8f0418577ab3cb6c4ad5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ApplicationVersionEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Artees.UnitySemVer; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | namespace Artees.AppVersion.Editor 9 | { 10 | [CustomEditor(typeof(ApplicationVersion))] 11 | internal class ApplicationVersionEditor : UnityEditor.Editor 12 | { 13 | public override void OnInspectorGUI() 14 | { 15 | base.OnInspectorGUI(); 16 | var semVer = ((ApplicationVersion) target).Version; 17 | var dirtyFields = GetDirtyFields(semVer); 18 | var messageArray = dirtyFields.Select(f => f.Message).ToArray(); 19 | var message = string.Join("\n", messageArray); 20 | if (string.IsNullOrEmpty(message)) return; 21 | EditorGUILayout.HelpBox(message, MessageType.Warning); 22 | EditorGUILayout.BeginHorizontal(); 23 | EditorGUILayout.Space(); 24 | var isApplied = GUILayout.Button("Apply", GUILayout.Width(50f)); 25 | EditorGUILayout.EndHorizontal(); 26 | if (!isApplied) return; 27 | Apply(dirtyFields); 28 | } 29 | 30 | private static Field[] GetDirtyFields(SemVer semVer) 31 | { 32 | var fields = new Field[] 33 | { 34 | new Field("Application version", 35 | PlayerSettings.bundleVersion, 36 | semVer, 37 | () => PlayerSettings.bundleVersion = semVer.Core), 38 | new Field("Mac build (CFBundleVersion)", 39 | PlayerSettings.macOS.buildNumber, 40 | semVer.Core, 41 | () => PlayerSettings.macOS.buildNumber = semVer.Core), 42 | new Field("Android Bundle Version Code", 43 | PlayerSettings.Android.bundleVersionCode, 44 | semVer.AndroidBundleVersionCode, 45 | () => PlayerSettings.Android.bundleVersionCode = semVer.AndroidBundleVersionCode), 46 | new Field("iOS build (CFBundleVersion)", 47 | PlayerSettings.iOS.buildNumber, 48 | semVer.Core, 49 | () => PlayerSettings.iOS.buildNumber = semVer.Core) 50 | }; 51 | return fields.Where(f => f.IsDirty).ToArray(); 52 | } 53 | 54 | private static void Apply(IEnumerable dirtyFields) 55 | { 56 | foreach (var f in dirtyFields) 57 | { 58 | f.ApplyField(); 59 | } 60 | } 61 | 62 | public static void Apply(SemVer semVer) 63 | { 64 | var dirtyFields = GetDirtyFields(semVer); 65 | Apply(dirtyFields); 66 | } 67 | 68 | private abstract class Field 69 | { 70 | protected readonly string Name; 71 | 72 | public readonly Action ApplyField; 73 | 74 | protected Field(string name, Action applyField) 75 | { 76 | Name = name; 77 | ApplyField = applyField; 78 | } 79 | 80 | public abstract bool IsDirty { get; } 81 | 82 | public abstract string Message { get; } 83 | } 84 | 85 | private class Field : Field where T : IEquatable 86 | { 87 | private readonly T _currentValue; 88 | private readonly T _newValue; 89 | 90 | public Field(string name, T currentValue, T newValue, Action applyField) : base(name, applyField) 91 | { 92 | _currentValue = currentValue; 93 | _newValue = newValue; 94 | } 95 | 96 | public override bool IsDirty => !Equals(_currentValue, _newValue); 97 | 98 | public override string Message => $"{Name}: {_currentValue} --> {_newValue}"; 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /Editor/ApplicationVersionEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a87543e74627c60439ab865424763967 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Artees.ApplicationVersion.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Artees.ApplicationVersion.Editor", 3 | "references": [ 4 | "GUID:5c3f1380e574b164a89bcd1cbdf7b747", 5 | "GUID:c7f2f2911de381941be7186214305448" 6 | ], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [] 17 | } -------------------------------------------------------------------------------- /Editor/Artees.ApplicationVersion.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c03961c041b965b4aa69ca6b82a49346 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /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: d19a71f8aaed6e940b17a55e4e467248 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Application Version 2 | 3 | [![openupm](https://img.shields.io/npm/v/games.artees.application-version?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/games.artees.application-version/) 4 | 5 | A tool for Unity Editor allowing you to update the version number of your application and synchronize it with the iOS/macOS build number and the Android bundle version code. 6 | 7 | ![Property drawer](https://github.com/Artees/Unity-Application-Version/raw/master/ApplicationVersion.png) 8 | 9 | # Installation 10 | Install the package **games.artees.application-version** using [my package registry](https://artees.games/upm). 11 | 12 | Or install via the [OpenUPM registry](https://openupm.com/packages/games.artees.application-version/). (Requires [openupm-cli](https://github.com/openupm/openupm-cli)) 13 | 14 | ``` 15 | openupm add games.artees.application-version 16 | ``` 17 | 18 | # Usage 19 | Select the context menu named "Create/Artees/Application Version" in the Project window. 20 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6760e1fbf80eee84996d49ca9d2af356 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name" : "games.artees.application-version", 4 | "version" : "1.0.0", 5 | "displayName" : "Application Version", 6 | "description" : "A tool for Unity Editor allowing you to update the version number of your application and synchronize it with the iOS/Mac build number and the Android bundle version code", 7 | "unity" : "2019.2", 8 | "unityRelease" : "", 9 | "dependencies" : { 10 | "games.artees.semver" : "0.3.3" 11 | }, 12 | "keywords" : [ 13 | ], 14 | "author" : { 15 | "name" : "Artees", 16 | "email" : "yo@artees.games", 17 | "url" : "https://github.com/Artees/Unity-Application-Version" 18 | } 19 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccdb7fabc488f45478d34829cf1adcf9 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 11500000, guid: 305d72b64a2242c0b6ff1d70a6bc89f4, type: 3} 11 | name: games.artees.application-version 12 | version: 1.0.0 13 | displayName: Application Version 14 | description: A tool for Unity Editor allowing you to update the version number of 15 | your application and synchronize it with the iOS/Mac build number and the Android 16 | bundle version code 17 | unity: 2019.2 18 | unityRelease: 19 | dependencies: 20 | keyValuePairs: 21 | - key: games.artees.semver 22 | value: 0.3.3 23 | keywords: [] 24 | author: 25 | name: Artees 26 | email: yo@artees.games 27 | url: 28 | autoExportJson: 1 29 | registryUrl: https://upm.artees.games:4873 30 | --------------------------------------------------------------------------------