├── Documentation~ ├── toc.yml ├── manual │ └── toc.yml ├── filterConfig.yml ├── templates │ └── darkfx │ │ ├── partials │ │ ├── footer.tmpl.partial │ │ ├── affix.tmpl.partial │ │ └── head.tmpl.partial │ │ └── styles │ │ └── toggle-theme.js └── docfx.json ├── Editor ├── Icons │ ├── logo.png │ ├── auto_16.png │ ├── auto_32.png │ ├── ristbar.png │ ├── rotate.png │ ├── equals_100.png │ ├── singleton.png │ ├── NamespaceConfigurationIcon.png │ ├── Icon.cs.meta │ ├── logo.png.meta │ ├── auto_16.png.meta │ ├── auto_32.png.meta │ ├── rotate.png.meta │ ├── singleton.png.meta │ ├── NamespaceConfigurationIcon.png.meta │ ├── equals_100.png.meta │ ├── Icon.cs │ └── ristbar.png.meta ├── Icons.meta ├── Tools.meta ├── Attributes.meta ├── Behaviours.meta ├── Utilities.meta ├── Lachee.Utilities.Editor.asmdef.meta ├── Behaviours │ ├── PerCameraSettings.meta │ └── PerCameraSettings │ │ ├── GlobalShaderPropertyPropertyDrawer.cs.meta │ │ └── GlobalShaderPropertyPropertyDrawer.cs ├── Tools │ ├── BoneViewer.cs.meta │ ├── EOLConversion.cs.meta │ ├── GitUpdater.cs.meta │ ├── HelpContext.cs.meta │ ├── NamespaceEditor.cs.meta │ ├── NamespaceProcessor.cs.meta │ ├── ReferenceFilter.cs.meta │ ├── AssemblyDefinitionSolutionProcessor.cs.meta │ ├── NamespaceConfiguration.cs.meta │ ├── HelpContext.cs │ ├── AssemblyDefinitionSolutionProcessor.cs │ ├── NamespaceConfiguration.cs │ ├── NamespaceEditor.cs │ ├── GitUpdater.cs │ ├── ReferenceFilter.cs │ └── EOLConversion.cs ├── Attributes │ ├── EditorButtons.cs.meta │ ├── LabelDrawer.cs.meta │ ├── SlideDrawer.cs.meta │ ├── ToggleDrawer.cs.meta │ ├── EnumFlagDrawer.cs.meta │ ├── ReadonlyDrawer.cs.meta │ ├── AutoAttributeDrawer.cs.meta │ ├── AutoAttributeEditor.cs.meta │ ├── AutoAttributeWindow.cs.meta │ ├── SceneAttributeDrawer.cs.meta │ ├── LabelDrawer.cs │ ├── ReadonlyDrawer.cs │ ├── EditorButtons.cs │ ├── ToggleDrawer.cs │ ├── SceneAttributeDrawer.cs │ ├── AutoAttributeDrawer.cs │ ├── AutoAttributeWindow.cs │ ├── SlideDrawer.cs │ └── EnumFlagDrawer.cs ├── Utilities │ ├── Extensions.cs.meta │ ├── RandomListDrawer.cs.meta │ ├── UnityEventDrawer.cs.meta │ ├── UnityEventDrawer.cs │ └── Extensions.cs └── Lachee.Utilities.Editor.asmdef ├── .github ├── FUNDING.yml └── workflows │ ├── documentation.yml │ └── release.yml ├── LICENSE.meta ├── README.md.meta ├── package.json.meta ├── Editor.meta ├── Runtime.meta ├── Runtime ├── UYAML.meta ├── Attributes.meta ├── Behaviours.meta ├── Utilities.meta ├── Lachee.Utilities.Runtime.asmdef.meta ├── UYAML │ ├── Parser.cs.meta │ ├── Polyfil.cs.meta │ ├── Writer.cs.meta │ ├── Entities.cs.meta │ ├── Polyfil.cs │ └── Writer.cs ├── Utilities │ ├── Circle.cs.meta │ ├── GLUtils.cs.meta │ ├── Lazy.cs.meta │ ├── Linq.cs.meta │ ├── Logger.cs.meta │ ├── Mathl.cs.meta │ ├── Extensions.cs.meta │ ├── Instantiator.cs.meta │ ├── MeshBuilder.cs.meta │ ├── RandomList.cs.meta │ ├── RandomListInt.cs.meta │ ├── SortedGizmos.cs.meta │ ├── Singleton.cs.meta │ ├── Lazy.cs │ ├── Instantiator.cs │ ├── Logger.cs │ ├── Circle.cs │ ├── Mathl.cs │ ├── GLUtils.cs │ ├── Extensions.cs │ ├── RandomList.cs │ ├── RandomListInt.cs │ └── SortedGizmos.cs ├── Attributes │ ├── AutoAttribute.cs.meta │ ├── ButtonAttribute.cs.meta │ ├── EnumFlagAttribute.cs.meta │ ├── LabelAttribute.cs.meta │ ├── ReadonlyAttribute.cs.meta │ ├── SceneAttribute.cs.meta │ ├── SlideAttribute.cs.meta │ ├── ToggleAttribute.cs.meta │ ├── SceneAttribute.cs │ ├── EnumFlagAttribute.cs │ ├── LabelAttribute.cs │ ├── SlideAttribute.cs │ ├── ReadonlyAttribute.cs │ ├── ButtonAttribute.cs │ ├── ToggleAttribute.cs │ └── AutoAttribute.cs ├── Behaviours │ ├── PerCameraSettings.cs.meta │ ├── Rotate.cs.meta │ ├── Rotate.cs │ └── PerCameraSettings.cs └── Lachee.Utilities.Runtime.asmdef ├── package.json ├── LICENSE ├── .gitignore └── README.md /Documentation~/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Scripting Reference 2 | href: api/ -------------------------------------------------------------------------------- /Editor/Icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/logo.png -------------------------------------------------------------------------------- /Editor/Icons/auto_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/auto_16.png -------------------------------------------------------------------------------- /Editor/Icons/auto_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/auto_32.png -------------------------------------------------------------------------------- /Editor/Icons/ristbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/ristbar.png -------------------------------------------------------------------------------- /Editor/Icons/rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/rotate.png -------------------------------------------------------------------------------- /Editor/Icons/equals_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/equals_100.png -------------------------------------------------------------------------------- /Editor/Icons/singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/singleton.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | ko_fi: 3 | lachee 4 | github: 5 | lachee 6 | -------------------------------------------------------------------------------- /Documentation~/manual/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Coniunctis nec qui 2 | href: e.md 3 | - name: Etiam nantemque exul 4 | href: etiam.md -------------------------------------------------------------------------------- /Editor/Icons/NamespaceConfigurationIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lachee/unity-utilities/HEAD/Editor/Icons/NamespaceConfigurationIcon.png -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 110692ee0ccc2234a959f66476f8ea2a 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36e531124d6bc78489917fa2fec7a10c 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e09572b22cb71564fbdb04153014fff6 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c868bacaf0a0aaf4d9e5c0abd3ea536d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3380ade03c80ded459b47490ab40833c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Icons.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6a17b2d536163d5468bcabb2ba59b5a3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Tools.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f4edb6f9d048e8d438717cced303b5dc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/UYAML.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc497a82ef8307b44a393a277729ede2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Attributes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cf907ffe4dee81b4180343b5b568d4da 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Behaviours.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49133c7508567cf47a0bdee0010f6fd1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Utilities.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6cb6a1b62110c8944844e665cfb8a437 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Attributes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 41a34bc3e84a57540992ee1fecf9c8ee 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Behaviours.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: deb0cbb458c76634da3cbe7b3ad977fa 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Utilities.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d0da5a0e1c765b3498fa4f4f52549c13 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Lachee.Utilities.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd84c76bc9d1b4242a69d9d44206d30b 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Lachee.Utilities.Runtime.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aa08d19502347e74bb216b7098a7c7c9 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/filterConfig.yml: -------------------------------------------------------------------------------- 1 | apiRules: 2 | - include: 3 | uidRegex: ^Lachee 4 | type: Namespace 5 | - include: 6 | uidRegex: ^Global 7 | type: Namespace 8 | - exclude: 9 | uidRegex: .* 10 | type: Namespace -------------------------------------------------------------------------------- /Editor/Behaviours/PerCameraSettings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce3b23b620fab1b46b24a1c09e333721 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Icons/Icon.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7455afed3e3f9d641a08f3bb9f009588 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UYAML/Parser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad337490d1e6ce54baf2e4cd9e74a049 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UYAML/Polyfil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 385c4bb70c6b5db49a0968d74e17ff96 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UYAML/Writer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 14c3ba875124e104d84c548e9f6a6904 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/BoneViewer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78cfe582510b4dd4cbf407e5c06b1e16 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/EOLConversion.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c54f0e50e28df2c4eafabe3416c4f442 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/GitUpdater.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f67c62fb5c7997d4b84a4b3ddc3a5bcf 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/HelpContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9ee6176bd0ecc54b8b6282b29915b99 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UYAML/Entities.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b59d73fe5f213c142925193e0a3634d6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Circle.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bcffa7e22c19efe4dacbf713e76142fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/GLUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6e0ce89c01389f948a7d83ae2f2f2070 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Lazy.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a68523e149c652c40b8d02d2b6c449f3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Linq.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad473949bcb467d4688edab682bfdb60 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Logger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec481dfa7b84f624dac37d54a9a8905f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Mathl.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c773c0698b93a254290f6267633d19e0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/EditorButtons.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c5413be549728f4bb6f9b963101bda6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/LabelDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b289015868b2e2247a4c65e4fd30331a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/SlideDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3f730b23f88436d44a81199f3fe19f96 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/ToggleDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42d64334a7eb0584c9d3e678d3abd330 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/NamespaceEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2b8fed207083f0648ad35fefe63bf408 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/NamespaceProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee60cd507c0b5894b9b8835971f47b94 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/ReferenceFilter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5742cac3d6fe42247b2fda6557284eeb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Utilities/Extensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 52ca2c5fac2b915448eb332ef2d950b1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Extensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9283e54564c2c6443a3508ed4cea3d05 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Instantiator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3953dd4c333e650479e39596e8ae6c75 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/MeshBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac44aa81e7ca412478e87e0ce1bc1085 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/RandomList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8bc63760442f91468ea8b3ab0ebf09b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/RandomListInt.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bfacf32ef0bafc34fb0ffed5d04759e1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/SortedGizmos.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 050dd1df794a8bb4ebe9a4db19854cf8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/EnumFlagDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c9f0d789af35f14f989feaed6d5d79f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/ReadonlyDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8dbe27332531f8243b3b605ddf17a91a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Lachee.Utilities.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lachee.Utilities.Editor", 3 | "references": [ 4 | "Lachee.Utilities.Runtime" 5 | ], 6 | "optionalUnityReferences": [], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false 12 | } -------------------------------------------------------------------------------- /Editor/Utilities/RandomListDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ecdf426be3ebffe4392ab937c5b5ba46 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Utilities/UnityEventDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26b1120c418121c43a9c24c7a8761c05 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/AutoAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5c7f6f0e12790c4aab0ba504206e8e4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/ButtonAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aebe9a70ebe34124882c6125959ec5ee 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/EnumFlagAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ea247670d33e41409e1e470a1135d0c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/LabelAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 705b6e02519497a44a250e76a616990a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/ReadonlyAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e855811ac64d3bf478102f67485d4144 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/SceneAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5928fc0887864ff4b9ba45c9f8492893 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/SlideAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c88eb4a65f10574facb6e44f249745a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/ToggleAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 604eb05d710617143b068fd8702b3b27 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Behaviours/PerCameraSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 52910d178c1a15949aacddc8283dc801 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/AutoAttributeDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3b0d697fa685fa64b885153aedbce5b9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/AutoAttributeEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f377e5c2ecefaa46adde92497907269 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/AutoAttributeWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48d6fcaefc643cd45a3b5c8ed6e96984 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Attributes/SceneAttributeDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 166a58f6bfa4fb243a165c1ba0142c2e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/AssemblyDefinitionSolutionProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 475dc5f4c43e7274296178e0a425ee67 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Behaviours/PerCameraSettings/GlobalShaderPropertyPropertyDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7d5b365cac0fce469077acad8d02269 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Attributes/SceneAttribute.cs: -------------------------------------------------------------------------------- 1 | using Lachee.Utilities; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | 7 | namespace Lachee.Attributes 8 | { 9 | [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = true)] 10 | public class SceneAttribute : PropertyAttribute 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Runtime/Behaviours/Rotate.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 646789c2fa18f5e45bf7720fa44d5811 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: 7b6390cac0a91ee40974a85c36c4e746, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utilities/Singleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec79f4415f5958643b8d7d8a96a0c1b5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: 6cdaa83adc4f44a4da1d2ce7b0560e8d, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/NamespaceConfiguration.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 04fef427cde48524baa574e93d6be103 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: 54d19a95e9b1ba74ca29d8a0a334d499, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Tools/HelpContext.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using UnityEditor; 3 | 4 | namespace Lachee.Tools.Editor 5 | { 6 | public class HelpContext : UnityEditor.Editor 7 | { 8 | [MenuItem("Help/Scripting Reference Lachee Utils", priority = 100)] 9 | public static void HelpContextMenu() 10 | { 11 | Process.Start("https://lachee.github.io/unity-utilities"); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Runtime/Lachee.Utilities.Runtime.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lachee.Utilities.Runtime", 3 | "rootNamespace": "Lachee", 4 | "references": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": true, 11 | "defineConstraints": [], 12 | "versionDefines": [], 13 | "noEngineReferences": false 14 | } -------------------------------------------------------------------------------- /Runtime/Behaviours/Rotate.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | namespace Lachee.Behaviours 5 | { 6 | /// 7 | /// Spins an object at the given speed 8 | /// 9 | public class Rotate : MonoBehaviour 10 | { 11 | public Vector3 speed = Vector3.one; 12 | private void Update() 13 | { 14 | transform.Rotate(speed * Time.deltaTime); 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.lachee.utilities", 3 | "version": "1.6.3", 4 | "displayName": "Lachee's Utilities", 5 | "description": "Bunch of utility functionality", 6 | "unity": "2019.1", 7 | "documentationUrl": "https://lachee.github.io/unity-utilities/", 8 | "changelogUrl": "https://github.com/Lachee/unity-utilities/commits/master", 9 | "license": "MIT", 10 | "dependencies": { }, 11 | "keywords": [ 12 | "Singleton", 13 | "Utility" 14 | ], 15 | "author": { 16 | "name": "Lachee", 17 | "url": "https://lachee.dev" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Editor/Attributes/LabelDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Attributes.Editor 5 | { 6 | [CustomPropertyDrawer(typeof(LabelAttribute))] 7 | public class LabelDrawer : PropertyDrawer 8 | { 9 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 10 | { 11 | LabelAttribute attr = (LabelAttribute)attribute; 12 | if (label != GUIContent.none) label = attr.label; 13 | EditorGUI.PropertyField(position, property, label, true); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Editor/Tools/AssemblyDefinitionSolutionProcessor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Lachee.Tools.Editor 4 | { 5 | /// 6 | /// Fixes Unity generating incorrect solutions for Assembly Definitions. 7 | /// 8 | /// Solution provided by Unity Forums. 9 | /// 10 | /// 11 | public class AssemblyDefinitionSolutionProcessor : AssetPostprocessor 12 | { 13 | private static string OnGeneratedCSProject(string path, string content) 14 | { 15 | return content.Replace("false", "true"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Runtime/Attributes/EnumFlagAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Lachee.Attributes 4 | { 5 | /// 6 | /// Assign this attribute to enums to give them a mask popup within unity. 7 | /// 8 | public class EnumFlagAttribute : PropertyAttribute 9 | { 10 | public string displayName = ""; 11 | public bool isReadonly = false; 12 | public bool buttonMode = true; 13 | 14 | public EnumFlagAttribute() { } 15 | 16 | /// 17 | /// Make the enum a flag display 18 | /// 19 | /// The display name 20 | /// Should it be just text instead (readonly)? 21 | public EnumFlagAttribute(string name = "", bool isReadonly = false, bool isButtons = true) 22 | { 23 | this.displayName = name; 24 | this.isReadonly = isReadonly; 25 | this.buttonMode = isButtons; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Lachee 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 | -------------------------------------------------------------------------------- /Documentation~/templates/darkfx/partials/footer.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | -------------------------------------------------------------------------------- /Runtime/Attributes/LabelAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Attributes 5 | { 6 | /// 7 | /// Makes object readonly in the editor. 8 | /// 9 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct, Inherited = true)] 10 | public class LabelAttribute : PropertyAttribute 11 | { 12 | /// 13 | /// The label and tooltip for the property. 14 | /// 15 | public GUIContent label; 16 | 17 | /// 18 | /// Creates a label 19 | /// 20 | /// The name of the property 21 | /// The tooltip for the property 22 | public LabelAttribute(string label, string tooltip = "") 23 | { 24 | this.label = new GUIContent(label, tooltip); 25 | } 26 | 27 | /// 28 | /// Creates a new label from the GUIContent 29 | /// 30 | /// 31 | public LabelAttribute(GUIContent content) 32 | { 33 | this.label = content; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Editor/Attributes/ReadonlyDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Attributes.Editor 5 | { 6 | [CustomPropertyDrawer(typeof(ReadonlyAttribute))] 7 | public class ReadonlyDrawer : PropertyDrawer 8 | { 9 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 10 | { 11 | ReadonlyAttribute attr = (ReadonlyAttribute)attribute; //The attribute data 12 | bool playMode = Application.isPlaying; //Are we currently in playmode? 13 | 14 | //If we are to be hidden, end here 15 | if (attr.hideInEditmode && !playMode) return; 16 | 17 | //Is the element enabled? 18 | bool enabled = (playMode && attr.editableInPlaymode) || (!playMode && attr.editableInEditmode); 19 | 20 | //Enable/disable the property 21 | bool wasEnabled = GUI.enabled; 22 | GUI.enabled = enabled; 23 | 24 | //Check if we should draw the property 25 | EditorGUI.PropertyField(position, property, label, true); 26 | 27 | //Ensure that the next property that is being drawn uses the correct settings 28 | GUI.enabled = wasEnabled; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Runtime/Utilities/Lazy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace Lachee.Utilities 9 | { 10 | /// 11 | /// Lazy fetching of components. 12 | /// The component will not be fetched wtih GetComponent until .Value is called for the first time. 13 | /// 14 | /// Component to fetch 15 | [System.Obsolete("Use Auto Attributes now")] 16 | public class Lazy where T : Component 17 | { 18 | private Component parent; 19 | private bool _initialized; 20 | private T _component; 21 | 22 | public Lazy(Component parent) { 23 | this.parent = parent; 24 | } 25 | 26 | public T Value 27 | { 28 | get 29 | { 30 | if (_initialized) return _component; 31 | _component = parent.GetComponent(); 32 | _initialized = true; 33 | return _component; 34 | } 35 | set 36 | { 37 | _component = value; 38 | _initialized = true; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Runtime/Attributes/SlideAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace Lachee.Attributes 9 | { 10 | [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] 11 | public sealed class SlideAttribute : PropertyAttribute 12 | { 13 | public float Min { get; } 14 | public float Max { get; } 15 | 16 | public GUIContent LeftLabel { get; } 17 | public GUIContent RightLabel { get; } 18 | 19 | public SlideAttribute(float min, float max) 20 | { 21 | this.Min = min; 22 | this.Max = max; 23 | LeftLabel = null; 24 | RightLabel = null; 25 | } 26 | 27 | public SlideAttribute(float min, float max, string leftLabel, string rightLabel) 28 | : this(min, max, new GUIContent(leftLabel), new GUIContent(rightLabel)) { } 29 | 30 | public SlideAttribute(float min, float max, GUIContent leftLabel, GUIContent rightLabel) 31 | { 32 | this.Min = min; 33 | this.Max = max; 34 | this.LeftLabel = leftLabel; 35 | this.RightLabel = rightLabel; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Documentation~/templates/darkfx/styles/toggle-theme.js: -------------------------------------------------------------------------------- 1 | const sw = document.getElementById("switch-style"), sw_mobile = document.getElementById("switch-style-m"), b = document.body; 2 | if (b) { 3 | function toggleTheme(target, dark) { 4 | target.classList.toggle("dark-theme", dark) 5 | target.classList.toggle("light-theme", !dark) 6 | } 7 | 8 | function switchEventListener() { 9 | toggleTheme(b, this.checked); 10 | if (window.localStorage) { 11 | this.checked ? localStorage.setItem("theme", "dark-theme") : localStorage.setItem("theme", "light-theme") 12 | } 13 | } 14 | 15 | var isDarkTheme = !window.localStorage || !window.localStorage.getItem("theme") || window.localStorage && localStorage.getItem("theme") === "dark-theme"; 16 | 17 | if(sw && sw_mobile){ 18 | sw.checked = isDarkTheme; 19 | sw_mobile.checked = isDarkTheme; 20 | 21 | sw.addEventListener("change", switchEventListener); 22 | sw_mobile.addEventListener("change", switchEventListener); 23 | 24 | // sync state between switches 25 | sw.addEventListener("change", function() { 26 | sw_mobile.checked = this.checked; 27 | }); 28 | 29 | sw_mobile.addEventListener("change", function() { 30 | sw.checked = this.checked; 31 | }); 32 | } 33 | 34 | toggleTheme(b, isDarkTheme); 35 | } -------------------------------------------------------------------------------- /Documentation~/templates/darkfx/partials/affix.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ====== # 2 | # Autogenerated VS/MD solution and project files 3 | # ====== # 4 | *.csproj 5 | *.unityproj 6 | *.sln 7 | *.suo 8 | *.user 9 | *.userprefs 10 | *.pidb 11 | *.booproj 12 | 13 | # ====== # 14 | # ReSharper is a .NET coding add-in 15 | # ====== # 16 | _ReSharper*/ 17 | *.[Rr]e[Ss]harper 18 | 19 | # ====== # 20 | # DotCover is a Code Coverage Tool 21 | # ====== # 22 | *.dotCover 23 | 24 | # ====== # 25 | # NCrunch 26 | # ====== # 27 | *.ncrunch* 28 | .*crunch*.local.xml 29 | 30 | # ====== # 31 | # Unity3D Generated File On Crash Reports 32 | # ====== # 33 | sysinfo.txt 34 | 35 | # ====== # 36 | # OS Generated 37 | # ====== # 38 | .DS_Store* 39 | ._* 40 | .Spotlight-V100 41 | .Trashes 42 | ehthumbs.db 43 | Thumbs.db 44 | $RECYCLE.BIN/ 45 | Desktop.ini 46 | 47 | # ====== # 48 | # Blender backup files 49 | # ====== # 50 | *.blend[1-9] 51 | *.blend[1-9].meta 52 | 53 | # ====== # 54 | # Sourcetree backup files # 55 | # ====== # 56 | *.orig 57 | *.orig.meta 58 | 59 | # ====== # 60 | # Visual Code files 61 | # ====== # 62 | VSCode.meta 63 | VSCode/* 64 | .vscode 65 | 66 | # ====== # 67 | # Others # 68 | # ====== # 69 | .~lock.* 70 | .vs/ 71 | *_backup 72 | *_backup.meta 73 | *.~*#* 74 | /_site 75 | /tools 76 | */obj/* 77 | Documentation/api/* 78 | Documentation/manual/changelog.* 79 | Documentation/index.* 80 | !.github/workflows/increment_version.sh 81 | 82 | 83 | _site.meta 84 | Documentation/**/*.meta 85 | Documentation/obj 86 | Documentation/api 87 | Scripts/Attributes/obj* -------------------------------------------------------------------------------- /Documentation~/templates/darkfx/partials/head.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Oscar Vasquez. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | 4 | 5 | 6 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} 7 | 8 | 9 | 10 | {{#_description}}{{/_description}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{#_noindex}}{{/_noindex}} 18 | {{#_enableSearch}}{{/_enableSearch}} 19 | {{#_enableNewTab}}{{/_enableNewTab}} 20 | -------------------------------------------------------------------------------- /Runtime/Attributes/ReadonlyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Attributes 5 | { 6 | /// 7 | /// Makes object readonly in the editor. 8 | /// 9 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct, Inherited = true)] 10 | public class ReadonlyAttribute : PropertyAttribute 11 | { 12 | /// 13 | /// Hide the property all together while in edit mode? 14 | /// 15 | public bool hideInEditmode = false; 16 | 17 | /// 18 | /// Allow the field to be editable in playmode? 19 | /// 20 | public bool editableInPlaymode = false; 21 | 22 | /// Allow the field to be editable in editmode? 23 | public bool editableInEditmode = false; 24 | 25 | /// 26 | /// Marks this attribute as readonly in the inspector. 27 | /// 28 | /// Hide the property all together while in edit mode? 29 | /// Allow the field to be editable in playmode? 30 | public ReadonlyAttribute(bool hideInEditmode = false, bool editableInPlaymode = false, bool editableInEditmode = false) 31 | { 32 | this.hideInEditmode = hideInEditmode; 33 | this.editableInPlaymode = editableInPlaymode; 34 | this.editableInEditmode = editableInEditmode; 35 | } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /Editor/Tools/NamespaceConfiguration.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEditor; 6 | using System.Linq; 7 | 8 | namespace Lachee.Tools.Editor 9 | { 10 | /// 11 | /// Automatic namespace configuration 12 | /// 13 | public class NamespaceConfiguration : ScriptableObject 14 | { 15 | /// 16 | /// The namespace to apply to all files under this configuration 17 | /// 18 | [field: SerializeField] 19 | public string RootNamespace { get; set; } 20 | /// 21 | /// Indicates if files should automatically be namespaced 22 | /// 23 | [field: SerializeField] 24 | public bool IsAutomatic { get; set; } 25 | /// 26 | /// Include subdirectories as sub-namespaces 27 | /// 28 | [field: SerializeField] 29 | public bool IncludeSubDirectories { get; set; } 30 | /// 31 | /// Format the documents with dotnet format after namespacing 32 | /// 33 | [field: SerializeField] 34 | public bool FormatDocument { get; set; } 35 | 36 | public void Reset() 37 | { 38 | RootNamespace = NamespaceProcessor.GetNamespaceForNewConfiguration(AssetDatabase.GetAssetPath(this)); 39 | IsAutomatic = true; 40 | IncludeSubDirectories = true; 41 | FormatDocument = true; 42 | } 43 | 44 | private void OnValidate() 45 | { 46 | RootNamespace = RootNamespace.Trim('.', ' '); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Runtime/Attributes/ButtonAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Lachee.Attributes 4 | { 5 | /// 6 | /// This attribute gives methods buttons within the editor inspector. This will allow for quick execution of the method within the editor. Similar to how ContexMenu works. 7 | /// 8 | [System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)] 9 | public class ButtonAttribute : PropertyAttribute 10 | { 11 | /// 12 | /// The label to draw the button as. 13 | /// 14 | public string Label { get; private set; } 15 | 16 | /// 17 | /// The colour to draw the button in. 18 | /// 19 | public Color Color { get; private set; } 20 | 21 | /// 22 | /// Creates a new button in the inspector 23 | /// 24 | public ButtonAttribute() 25 | { 26 | this.Label = null; 27 | this.Color = Color.white; 28 | } 29 | 30 | /// 31 | /// Creates a new button in the inspector with specified label. 32 | /// 33 | /// The label to appear on the button 34 | public ButtonAttribute(string label) 35 | { 36 | this.Label = label; 37 | this.Color = Color.white; 38 | } 39 | 40 | /// 41 | /// Creates a new button in the inspector with specified label and colour. 42 | /// 43 | /// The label to appear on the button 44 | /// Red value of the colour 45 | /// Green value of the colour 46 | /// Blue value of the colour 47 | public ButtonAttribute(string label, byte r, byte g, byte b) 48 | { 49 | this.Label = label; 50 | this.Color = new Color32(r, g, b, 255); 51 | } 52 | 53 | 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Create Documentation 📚 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | # Build the documentation 10 | build: 11 | if: # Adding if-statement to prevent this job from running on packages using this template. 12 | # If you want to run this documentation job, just take out the if-field and value below. 13 | github.repository == 'lachee/unity-utilities' 14 | 15 | runs-on: windows-latest # Required by DocFX 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | 20 | - name: Install DocFX 21 | run: | 22 | choco install -y docfx 23 | docfx --version 24 | 25 | - name: Use README.md as index.md 26 | run: cp README.md Documentation~/index.md 27 | 28 | - name: Build 29 | run: docfx Documentation~/docfx.json -t default,templates/darkfx 30 | 31 | # Upload the generated documentation 32 | - name: Upload site artifact 33 | uses: actions/upload-artifact@v1 34 | with: 35 | name: _site 36 | path: _site # Must equals the 'build.dest' value on your docfx.json 37 | 38 | # Deploy the generated documentation to the gh-pages branch 39 | deploy: 40 | needs: build 41 | runs-on: ubuntu-latest 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v2 45 | 46 | 47 | # Download the generated documentation 48 | - name: Download site artifact 49 | uses: actions/download-artifact@v1 50 | with: 51 | name: _site 52 | 53 | - name: Deploy 54 | uses: peaceiris/actions-gh-pages@v3 55 | with: 56 | github_token: ${{ secrets.GITHUB_TOKEN }} 57 | publish_branch: gh-pages 58 | publish_dir: _site -------------------------------------------------------------------------------- /Runtime/Utilities/Instantiator.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Lachee.Utilities 4 | { 5 | /// 6 | /// Instantiates an object in a particular way. 7 | /// 8 | /// This functionality is useful when you have a list of objects spawning and they have pointers to their own functions to customise their end result. 9 | /// For example: List of Tower Defense Pieces, with some pieces with special post-placement rules like "shift to the left" 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// var spawner = new Instantiator(gameObject, (obj) => 15 | /// { 16 | /// return obj.GetComponent(); 17 | /// }); 18 | /// 19 | /// // Later: 20 | /// spawner.Instantiate(); 21 | /// 22 | public class Instantiator where T : Object 23 | { 24 | public GameObject prefab { get; } 25 | public Transform parent { get; set; } 26 | public Vector3 localPosition { get; set; } 27 | 28 | private System.Func callback; 29 | 30 | public Instantiator(GameObject prefab, System.Func callback) { 31 | this.prefab = prefab; 32 | this.callback = callback; 33 | } 34 | 35 | /// Spawns the object and returns the result of the post event 36 | public T Instantiate() 37 | { 38 | // Create the instance 39 | var instance = GameObject.Instantiate(prefab); 40 | 41 | // Set the parent 42 | if (parent != null) 43 | instance.transform.SetParent(parent); 44 | 45 | // Set local coordinate 46 | instance.transform.localPosition = localPosition; 47 | 48 | // Invoke the post event 49 | return callback?.Invoke(instance); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Documentation~/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "src": "..", 7 | "files": [ "Runtime/**/*.cs", "Editor/**/*.cs" ] 8 | } 9 | ], 10 | "globalNamespaceId": "Global", 11 | "dest": "api", 12 | "properties": { 13 | "DefineConstants": "UNITY_EDITOR=1" 14 | } 15 | } 16 | ], 17 | "build": { 18 | "globalMetadata": { 19 | "_appTitle": "Utilities", 20 | "_appFooter": "MIT by Lachee", 21 | "_enableSearch": true 22 | }, 23 | "content": [ 24 | { 25 | "files": [ 26 | "toc.yml", 27 | "index.md" 28 | ] 29 | }, 30 | { 31 | "src": "api", 32 | "files": [ 33 | "*.yml" 34 | ], 35 | "dest": "api" 36 | }, 37 | { 38 | "src": "manual", 39 | "files": [ 40 | "toc.yml", 41 | "*.md" 42 | ], 43 | "dest": "manual" 44 | } 45 | ], 46 | "overwrite": [ 47 | { 48 | "src": "..", 49 | "files": [ "Runtime/**/*.md", "Editor/**/*.md" ] 50 | } 51 | ], 52 | "resource": [ 53 | { 54 | "files": [ "resources/**/*" ] 55 | } 56 | ], 57 | "sitemap": 58 | { 59 | "baseUrl": "https://lachee.github.io/unity-utilities/", 60 | "changefreq": "yearly", 61 | "fileOptions": { 62 | "api/*": { 63 | "changefreq": "daily" 64 | } 65 | } 66 | }, 67 | "xref": [ "https://normanderwan.github.io/UnityXrefMaps/xrefmap.yml" ], 68 | "xrefService": [ "https://xref.docs.microsoft.com/query?uid={uid}" ], 69 | "dest": "../_site" 70 | } 71 | } -------------------------------------------------------------------------------- /Runtime/Attributes/ToggleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace Lachee.Attributes 9 | { 10 | /// Marks an attribute as togglable. 11 | [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] 12 | public sealed class ToggleAttribute : PropertyAttribute 13 | { 14 | /// The name of the field to store the toggle state under. 15 | /// Prefix with # for the current variable name 16 | /// 17 | /// [Toggle(Field: "use_#")] 18 | /// public Color color; 19 | /// public bool use_color; 20 | /// 21 | public string Field { get; private set; } 22 | 23 | public string Tooltip { get; private set; } 24 | 25 | /// 26 | /// Inverts the disable state of the UI element so that when ticked it is disabeld 27 | /// 28 | public bool Invert { get; private set; } 29 | 30 | /// 31 | /// Shows the checkbox to enable/disable he field 32 | /// 33 | public bool ShowCheckbox { get; set; } = true; 34 | 35 | /// Creates a toggle attribute with the default prefix of @Enabled 36 | public ToggleAttribute() 37 | { 38 | Field = "#Enabled"; 39 | Tooltip = "Toggle Attribute"; 40 | Invert = false; 41 | } 42 | 43 | public ToggleAttribute(string field) 44 | : this() 45 | { 46 | Field = field; 47 | } 48 | 49 | public ToggleAttribute(string field, string tooltip) 50 | : this() 51 | { 52 | Field = field; 53 | Tooltip = tooltip; 54 | } 55 | 56 | 57 | public ToggleAttribute(string field, string tooltip, bool invert) 58 | : this() 59 | { 60 | Field = field; 61 | Tooltip = tooltip; 62 | Invert = invert; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Editor/Attributes/EditorButtons.cs: -------------------------------------------------------------------------------- 1 | // Initial Concept by http://www.reddit.com/user/zaikman 2 | // Revised by http://www.reddit.com/user/quarkism 3 | 4 | using System; 5 | using System.Linq; 6 | using UnityEngine; 7 | using UnityEditor; 8 | using System.Reflection; 9 | 10 | namespace Lachee.Attributes.Editor 11 | { 12 | [CanEditMultipleObjects()] 13 | [CustomEditor(typeof(MonoBehaviour), true)] 14 | public class EditorButton : UnityEditor.Editor 15 | { 16 | public override void OnInspectorGUI() 17 | { 18 | base.OnInspectorGUI(); 19 | 20 | var mono = (MonoBehaviour)targets[0]; 21 | var methods = mono.GetType() 22 | .GetMembers(BindingFlags.Instance | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | 23 | BindingFlags.NonPublic) 24 | .Where(o => Attribute.IsDefined(o, typeof(ButtonAttribute))); 25 | 26 | 27 | foreach (var memberInfo in methods) 28 | { 29 | //Prepare the name 30 | string buttonText = memberInfo.Name; 31 | Color color = Color.white; 32 | 33 | //Get the button attributes 34 | ButtonAttribute[] attributes = (ButtonAttribute[])memberInfo.GetCustomAttributes(typeof(ButtonAttribute), false); 35 | if (attributes.Length != 0) 36 | { 37 | if (!string.IsNullOrEmpty(attributes[0].Label)) 38 | buttonText = attributes[0].Label; 39 | 40 | color = attributes[0].Color; 41 | } 42 | 43 | 44 | if (targets.Length > 1) 45 | buttonText += " x" + targets.Length; 46 | 47 | //Store previous colour 48 | Color pc = GUI.color; 49 | GUI.color = color; 50 | 51 | //Draw a button 52 | if (GUILayout.Button(new GUIContent(buttonText))) 53 | { 54 | var method = memberInfo as MethodInfo; 55 | for (int i = 0; i < targets.Length; i++) method.Invoke(targets[i], null); 56 | } 57 | 58 | //Restore the colour 59 | GUI.color = pc; 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Editor/Attributes/ToggleDrawer.cs: -------------------------------------------------------------------------------- 1 | using Lachee.Utilities.Editor; 2 | using System.Configuration; 3 | using System.Reflection; 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | namespace Lachee.Attributes.Editor 8 | { 9 | //TODO: Create a Optional drawer 10 | 11 | [CustomPropertyDrawer(typeof(ToggleAttribute))] 12 | public class ToggleDrawer : PropertyDrawer 13 | { 14 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 15 | { 16 | 17 | ToggleAttribute attr = (ToggleAttribute)attribute; //The attribute data 18 | string fieldName = attr.Field.Replace("#", property.propertyPath); 19 | 20 | SerializedProperty toggleProperty = property.serializedObject.FindProperty(fieldName); 21 | if (toggleProperty == null) 22 | { 23 | EditorGUI.HelpBox(position, $"Cannot find '{fieldName}'", MessageType.Error); 24 | 25 | Rect smolRect = new Rect(position.x + 200, position.y, position.width - 200, position.height); 26 | EditorGUI.PropertyField(smolRect, property, label, true); 27 | } 28 | else 29 | { 30 | bool wasEnabled = GUI.enabled; 31 | int indentation = 0; 32 | 33 | //Check if we should draw the property 34 | if (attr.ShowCheckbox) 35 | { 36 | Rect iconBox = new Rect(position.x, position.y, 25, position.height); 37 | EditorGUI.PropertyField(iconBox, toggleProperty, new GUIContent("", attr.Tooltip)); 38 | indentation += 1; 39 | } 40 | 41 | Rect propBox = new Rect(position.x, position.y, position.width, position.height); 42 | GUI.enabled = attr.Invert ? !toggleProperty.boolValue : toggleProperty.boolValue; 43 | { 44 | EditorGUI.indentLevel += indentation; 45 | { 46 | EditorGUI.PropertyField(propBox, property, new GUIContent(label.text, label.tooltip), true); 47 | } 48 | EditorGUI.indentLevel -= indentation; 49 | } 50 | GUI.enabled = wasEnabled; 51 | 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Editor/Icons/logo.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ce5949d5a6b0b84b9b63aac8cfba763 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Icons/auto_16.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 766ff76c3b278b04cacf065bcdf65a3f 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Icons/auto_32.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 94530394c37cbd84fbc57648490809ac 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Icons/rotate.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b6390cac0a91ee40974a85c36c4e746 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Icons/singleton.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6cdaa83adc4f44a4da1d2ce7b0560e8d 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Icons/NamespaceConfigurationIcon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54d19a95e9b1ba74ca29d8a0a334d499 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: 1 36 | aniso: 1 37 | mipBias: 0 38 | wrapU: 0 39 | wrapV: 0 40 | wrapW: 0 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Editor/Tools/NamespaceEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.Linq; 6 | 7 | 8 | namespace Lachee.Tools.Editor 9 | { 10 | /// 11 | /// Handles context menus for the auto namespace 12 | /// 13 | public class NamespaceEditor : UnityEditor.Editor 14 | { 15 | [MenuItem("Assets/Create/C# Script Namespace", false, 100)] 16 | public static void CreateNamespaceConfiguration() 17 | { 18 | string filePath = AssetDatabase.GetAssetPath(Selection.activeObject) + "/"; 19 | string rootNamespace = NamespaceProcessor.GetNamespaceForNewConfiguration(filePath); 20 | filePath += rootNamespace + ".asset"; 21 | 22 | NamespaceConfiguration configuration = ScriptableObject.CreateInstance(); 23 | AssetDatabase.CreateAsset(configuration, filePath); 24 | AssetDatabase.SaveAssets(); 25 | 26 | // Update the asset 27 | configuration.Reset(); 28 | configuration.RootNamespace = rootNamespace; 29 | AssetDatabase.SaveAssetIfDirty(configuration); 30 | AssetDatabase.Refresh(); 31 | 32 | Selection.activeObject = configuration; 33 | } 34 | 35 | [MenuItem("Assets/Update Namespace", true)] 36 | private static bool ContextMenuVerifyMonoScriptValidation() => !Selection.objects.Any(o => !(o is MonoScript)); 37 | [MenuItem("Assets/Update Namespace", priority = 1000)] 38 | private static void ContextMenuVerifyMonoScript() 39 | { 40 | List formatQueue = new List(); 41 | foreach (var obj in Selection.objects) 42 | { 43 | string asset = AssetDatabase.GetAssetPath(obj); 44 | 45 | // Get the desired namespace and if we should be editing it 46 | string desiredNamespace = NamespaceProcessor.GetNamespace(asset, out var configuration); 47 | if (configuration == null) return; 48 | 49 | var systemPath = asset.Insert(0, Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("Assets"))); 50 | NamespaceProcessor.SetNamespace(systemPath, desiredNamespace); 51 | 52 | if (configuration.FormatDocument) 53 | formatQueue.Add(systemPath); 54 | } 55 | 56 | NamespaceProcessor.FormatScripts(formatQueue); 57 | AssetDatabase.Refresh(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Runtime/Utilities/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Utilities 5 | { 6 | /// 7 | /// Custom Logger for Unity that handles parenting and hierarchy of logs 8 | /// 9 | public class Logger : ILogHandler 10 | { 11 | public Logger Parent { get; } 12 | public string Tag { get; } 13 | 14 | public Logger(string tag) 15 | { 16 | Tag = $"[{tag}]"; 17 | } 18 | 19 | public Logger(Logger parent, string tag) : this(parent.Tag + tag) 20 | { 21 | Parent = parent; 22 | } 23 | 24 | public void Info(string format, params object[] args) 25 | => Info(format, null, args); 26 | public void Info(string format, UnityEngine.Object context, params object[] args) 27 | => LogFormat(LogType.Log, context, format, args); 28 | public void Info(object message) 29 | => Info(message, null); 30 | public void Info(object message, UnityEngine.Object context) 31 | => LogFormat(LogType.Log, context, message.ToString()); 32 | 33 | public void Warning(string format, params object[] args) 34 | => Warning(format, null, args); 35 | public void Warning(string format, UnityEngine.Object context, params object[] args) 36 | => LogFormat(LogType.Warning, context, format, args); 37 | public void Warning(object message) 38 | => Warning(message, null); 39 | public void Warning(object message, UnityEngine.Object context) 40 | => LogFormat(LogType.Warning, context, message.ToString()); 41 | 42 | public void Error(string format, params object[] args) 43 | => Error(format, null, args); 44 | public void Error(string format, UnityEngine.Object context, params object[] args) 45 | => LogFormat(LogType.Error, context, format, args); 46 | public void Error(object message) 47 | => Error(message, null); 48 | public void Error(object message, UnityEngine.Object context) 49 | => LogFormat(LogType.Error, context, message.ToString()); 50 | 51 | public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args) 52 | { 53 | #if !SILENT 54 | Debug.unityLogger.LogFormat(logType, context, Tag + " " + format, args); 55 | #endif 56 | } 57 | 58 | public void LogException(Exception exception, UnityEngine.Object context) 59 | { 60 | #if !SILENT 61 | Debug.unityLogger.LogException(exception, context); 62 | #endif 63 | } 64 | 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Editor/Tools/GitUpdater.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using UnityEditor; 5 | using Debug = UnityEngine.Debug; 6 | 7 | namespace Packages.com.lachee.utilties.Editor.Tools 8 | { 9 | class GitUpdater 10 | { 11 | internal static string GitPath { get; private set; } 12 | internal static string PackagePath => Path.GetFullPath("Packages/com.lachee.utilities/"); 13 | static GitUpdater() 14 | { 15 | #if UNITY_EDITOR_WIN 16 | GitPath = ExpandPath("git.exe"); 17 | #else 18 | GitPath = ExpandPath("git"); 19 | #endif 20 | } 21 | 22 | 23 | 24 | [MenuItem("Tools/Lachee/Update via Git", priority = 10000)] 25 | public static void HelpContextMenu() 26 | { 27 | UnityEngine.Debug.Log($"== GIT UPDATE BEGIN == \nGit Path:\t{GitPath}\nProject Path:\t{PackagePath}"); 28 | var proc = Process.Start(new ProcessStartInfo() 29 | { 30 | FileName = GitPath, 31 | Arguments = "pull", 32 | WorkingDirectory = PackagePath, 33 | CreateNoWindow = true, 34 | RedirectStandardOutput = true, 35 | UseShellExecute = false, 36 | }); 37 | Debug.Log("== GIT UPDATE RESULTS ==\n\n" + proc.StandardOutput.ReadToEnd()); 38 | } 39 | 40 | [MenuItem("Tools/Lachee/Update via Git", true, priority = 10000)] 41 | public static bool ValidateGitUpdate() 42 | { 43 | if (GitPath == null) 44 | return false; 45 | if (!PackagePath.Replace('\\', '/').Contains("Packages/com.lachee.utilities/")) 46 | return false; 47 | if (!Directory.Exists(PackagePath + ".git")) 48 | return false; 49 | return true; 50 | } 51 | 52 | static string ExpandPath(string exe) 53 | { 54 | exe = Environment.ExpandEnvironmentVariables(exe); 55 | if (!File.Exists(exe)) 56 | { 57 | if (Path.GetDirectoryName(exe) == String.Empty) 58 | { 59 | foreach (string test in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(';')) 60 | { 61 | string path = test.Trim(); 62 | if (!String.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exe))) 63 | return Path.GetFullPath(path); 64 | } 65 | } 66 | return null; 67 | } 68 | return Path.GetFullPath(exe); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Runtime/Attributes/AutoAttribute.cs: -------------------------------------------------------------------------------- 1 | using Lachee.Utilities; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | 7 | namespace Lachee.Attributes 8 | { 9 | /// Flag that controls how searching is handled within the 10 | [System.Flags] 11 | public enum AutoSearchFlag 12 | { 13 | /// Search the GameObject 14 | GameObject = 1, 15 | /// Search the children for the component 16 | Children = 2, 17 | /// Search the scene for the component 18 | Scene = 4, 19 | /// Searches the parent for the component 20 | Parent = 8 21 | } 22 | 23 | /// 24 | /// Automatically fetches attached components 25 | /// 26 | [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] 27 | public partial class AutoAttribute : PropertyAttribute 28 | { 29 | /// 30 | /// Hides the field from the inspector if the value is set. 31 | /// 32 | public bool Hidden { get; set; } 33 | 34 | /// 35 | /// Include children in the search for components 36 | /// If applied to an array, then all components found will be used 37 | /// If not applied to an array, then the first component found will be used 38 | /// 39 | public AutoSearchFlag SearchFlag { get; set; } 40 | 41 | /// Automatically fetches components and hides them in the inspector from this game object 42 | public AutoAttribute() : this(true, AutoSearchFlag.GameObject) { } 43 | 44 | /// 45 | /// Automatically fetches components from this game object. 46 | /// 47 | /// 48 | public AutoAttribute(bool hidden) : this(hidden, AutoSearchFlag.GameObject) { } 49 | 50 | /// 51 | /// Automatically fetches the components and hides them from the inspector 52 | /// 53 | /// 54 | public AutoAttribute(AutoSearchFlag mode) : this(true, mode) { } 55 | 56 | /// 57 | /// Automatically fetches the components 58 | /// 59 | /// 60 | /// 61 | public AutoAttribute(bool hidden, AutoSearchFlag mode) 62 | { 63 | this.Hidden = hidden; 64 | this.SearchFlag = mode; 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Editor/Behaviours/PerCameraSettings/GlobalShaderPropertyPropertyDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEngine; 5 | using Lachee.Behaviours; 6 | using Lachee.Editor.Icons; 7 | 8 | namespace Lachee.Editor.Behaviours 9 | { 10 | [CustomPropertyDrawer(typeof(PerCameraSettings.GlobalShaderProperty))] 11 | public class GlobalShaderPropertyPropertyDrawer : PropertyDrawer 12 | { 13 | 14 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 15 | { 16 | EditorGUI.BeginProperty(position, label, property); 17 | 18 | // Don't make child fields be indented 19 | var indent = EditorGUI.indentLevel; 20 | EditorGUI.indentLevel = 0; 21 | 22 | Rect rectName = new Rect(position.x, position.y, 150, position.height); 23 | Rect rectEq = new Rect(rectName.xMax + 5, position.y, 15, position.height); 24 | Rect rectValue = new Rect(rectEq.xMax + 5, position.y, 50, position.height); 25 | 26 | Rect rectResetLabel = new Rect(rectValue.xMax, position.y, 40, position.height); 27 | Rect rectReset = new Rect(rectResetLabel.xMax + 5, position.y, 15, position.height); 28 | Rect rectDefault = new Rect(rectReset.xMax + 5, position.y, 50, position.height); 29 | 30 | // Shift the right side so it sticks to the total width 31 | float diff = (position.width - rectDefault.xMax) + 50; 32 | rectResetLabel.x = rectResetLabel.x + diff; 33 | rectReset.x = rectReset.x + diff; 34 | rectDefault.x = rectDefault.x + diff; 35 | 36 | EditorGUI.PropertyField(rectName, property.FindPropertyRelative("name"), GUIContent.none); 37 | EditorGUI.LabelField(rectEq, new GUIContent(Icon.equals)); 38 | EditorGUI.PropertyField(rectValue, property.FindPropertyRelative("value"), GUIContent.none); 39 | EditorGUI.LabelField(rectResetLabel, new GUIContent("Resets")); 40 | 41 | var revertProperty = property.FindPropertyRelative("revert"); 42 | EditorGUI.PropertyField(rectReset, revertProperty, GUIContent.none); 43 | EditorGUI.BeginDisabledGroup(!revertProperty.boolValue); 44 | { 45 | EditorGUI.PropertyField(rectDefault, property.FindPropertyRelative("revertValue"), GUIContent.none); 46 | } 47 | EditorGUI.EndDisabledGroup(); 48 | 49 | // Set indent back to what it was 50 | EditorGUI.indentLevel = indent; 51 | 52 | EditorGUI.EndProperty(); 53 | } 54 | 55 | 56 | } 57 | } -------------------------------------------------------------------------------- /Editor/Tools/ReferenceFilter.cs: -------------------------------------------------------------------------------- 1 | #if !UNITY_2020_1_OR_NEWER 2 | using UnityEngine; 3 | using System.Collections; 4 | using UnityEditor; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | using System.Linq; 8 | 9 | public class ReferenceFilter : EditorWindow 10 | { 11 | [MenuItem("CONTEXT/Component/Find All References")] 12 | [MenuItem("GameObject/Component/Find All References")] 13 | private static void FindReferences(MenuCommand data) 14 | { 15 | Object context = data.context; 16 | if (context) 17 | { 18 | var comp = context as Component; 19 | if (comp) 20 | FindReferencesTo(comp); 21 | } 22 | } 23 | 24 | [MenuItem("Assets/Find All References")] 25 | private static void FindReferencesToAsset(MenuCommand data) 26 | { 27 | var selected = Selection.activeObject; 28 | if (selected) 29 | FindReferencesTo(selected); 30 | } 31 | 32 | private static void FindReferencesTo(Object to) 33 | { 34 | var referencedBy = new List(); 35 | var allObjects = Object.FindObjectsOfType(); 36 | for (int j = 0; j < allObjects.Length; j++) 37 | { 38 | var go = allObjects[j]; 39 | 40 | if (PrefabUtility.GetPrefabType(go) == PrefabType.PrefabInstance) 41 | { 42 | if (PrefabUtility.GetPrefabParent(go) == to) 43 | { 44 | Debug.Log(string.Format("Referenced by prefab ({1}) {0}", go.name, go.GetType()), go); 45 | referencedBy.Add(go); 46 | } 47 | } 48 | 49 | var components = go.GetComponents(); 50 | for (int i = 0; i < components.Length; i++) 51 | { 52 | var c = components[i]; 53 | if (!c) continue; 54 | 55 | var so = new SerializedObject(c); 56 | var sp = so.GetIterator(); 57 | 58 | while (sp.NextVisible(true)) 59 | if (sp.propertyType == SerializedPropertyType.ObjectReference) 60 | { 61 | if (sp.objectReferenceValue == to) 62 | { 63 | Debug.Log(string.Format("Referenced by ({1}) {0}: {2}", c.name, c.GetType(), sp.displayName), c); 64 | referencedBy.Add(c.gameObject); 65 | } 66 | } 67 | } 68 | } 69 | 70 | if (referencedBy.Any()) 71 | Selection.objects = referencedBy.ToArray(); 72 | else Debug.LogError("No references found in scene"); 73 | } 74 | } 75 | #endif -------------------------------------------------------------------------------- /Editor/Icons/equals_100.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87ac768d663d98246b24c3015d2ecf48 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 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 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMasterTextureLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 0 41 | wrapV: 0 42 | wrapW: 0 43 | nPOTScale: 1 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 0 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 0 56 | spriteTessellationDetail: -1 57 | textureType: 0 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | platformSettings: 69 | - serializedVersion: 3 70 | buildTarget: DefaultTexturePlatform 71 | maxTextureSize: 2048 72 | resizeAlgorithm: 0 73 | textureFormat: -1 74 | textureCompression: 1 75 | compressionQuality: 50 76 | crunchedCompression: 0 77 | allowsAlphaSplitting: 0 78 | overridden: 0 79 | androidETC2FallbackOverride: 0 80 | forceMaximumCompressionQuality_BC6H_BC7: 0 81 | spriteSheet: 82 | serializedVersion: 2 83 | sprites: [] 84 | outline: [] 85 | physicsShape: [] 86 | bones: [] 87 | spriteID: 88 | internalID: 0 89 | vertices: [] 90 | indices: 91 | edges: [] 92 | weights: [] 93 | secondaryTextures: [] 94 | nameFileIdTable: {} 95 | spritePackingTag: 96 | pSDRemoveMatte: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /Editor/Attributes/SceneAttributeDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Attributes.Editor 6 | { 7 | [CustomPropertyDrawer(typeof(SceneAttribute))] 8 | public class SceneAttributeDrawer: PropertyDrawer 9 | { 10 | const float HELP_BOX_HEIGHT = 20f; 11 | 12 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 13 | { 14 | var propertyIsValid = Validate(property); 15 | var oldScene = AssetDatabase.LoadAssetAtPath(property.stringValue); 16 | 17 | EditorGUI.BeginChangeCheck(); 18 | Rect sceneBox = new Rect(position.x, position.y, position.width, position.height - (propertyIsValid ? 0 : HELP_BOX_HEIGHT)); 19 | var newScene = EditorGUI.ObjectField(sceneBox, label, oldScene, typeof(SceneAsset), false) as SceneAsset; 20 | if (EditorGUI.EndChangeCheck()) 21 | { 22 | var newPath = AssetDatabase.GetAssetPath(newScene); 23 | property.stringValue = newPath; 24 | } 25 | 26 | if (!propertyIsValid) 27 | { 28 | Rect helpBoxRect = new Rect(position.x, position.y + position.height - HELP_BOX_HEIGHT, position.width, HELP_BOX_HEIGHT); 29 | 30 | EditorGUI.HelpBox(helpBoxRect, "The scene is not listed in the Build Settings. Please ensure it has been added.", MessageType.Warning); 31 | Rect helpButtonRect = new Rect(helpBoxRect.x + EditorGUIUtility.labelWidth, helpBoxRect.position.y, 150, helpBoxRect.height); 32 | if (GUI.Button(helpButtonRect, "Add to Build Settings")) 33 | { 34 | var originalScenes = EditorBuildSettings.scenes; 35 | var newScenes = new EditorBuildSettingsScene[originalScenes.Length + 1]; 36 | System.Array.Copy(originalScenes, newScenes, originalScenes.Length); 37 | var sceneToAdd = new EditorBuildSettingsScene(property.stringValue, true); 38 | newScenes[newScenes.Length - 1] = sceneToAdd; 39 | EditorBuildSettings.scenes = newScenes; 40 | EditorApplication.ExecuteMenuItem("File/Build Settings..."); 41 | } 42 | } 43 | 44 | } 45 | 46 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 47 | { 48 | var height = base.GetPropertyHeight(property, label); 49 | if (!Validate(property)) 50 | height += HELP_BOX_HEIGHT; 51 | 52 | return height; 53 | } 54 | 55 | public bool Validate(SerializedProperty property) 56 | { 57 | return EditorBuildSettings.scenes.Any(scene => scene.path == property.stringValue); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Runtime/UYAML/Polyfil.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lachee.UYAML 4 | { 5 | #if !NET_STANDARD 6 | internal static class NetStandardPolyfill { 7 | public static bool TryPop(this Stack stack, out T result) { 8 | result = default; 9 | if (stack.Count == 0) 10 | return false; 11 | result = stack.Pop(); 12 | return true; 13 | } 14 | 15 | public static bool TryAdd(this Dictionary dict, T key, K value) { 16 | if (dict.ContainsKey(key)) 17 | return false; 18 | dict.Add(key, value); 19 | return true; 20 | } 21 | 22 | public static string[] Split(this string str, char separator, int count) 23 | { 24 | return str.Split(new char[] { separator }, count); 25 | } 26 | } 27 | #endif 28 | 29 | #if UNITY_5_3_OR_NEWER 30 | public static class UExtensions { 31 | /// 32 | /// Replaces all fileIDs that match the given mapping 33 | /// 34 | /// 35 | /// 36 | public static void ReplaceFileID(this UProperty property, Dictionary map) { 37 | if (property.value is UObject obj) 38 | { 39 | foreach (var kp in obj.properties.Values) 40 | ReplaceFileID(kp, map); 41 | } 42 | else if (property.value is UArray arr) 43 | { 44 | foreach (var item in arr.items) 45 | ReplaceFileID(new UProperty(string.Empty, item), map); 46 | } 47 | else if (property.name == "fileID" && property.value is UValue value && long.TryParse(value.value, out var fileID)) 48 | { 49 | if (map.TryGetValue(fileID, out var dest)) { 50 | value.value = dest.ToString(); 51 | } 52 | } 53 | 54 | } 55 | 56 | /// 57 | /// Replaces all GUIDs inside the map. 58 | /// 59 | /// 60 | /// 61 | public static void ReplaceGUID(this UProperty property, Dictionary map) { 62 | if (property.name == "guid" && property.value is UValue value) 63 | { 64 | if (map.TryGetValue(value.value, out var dest)) 65 | value.value = dest.ToString(); 66 | } 67 | else if (property.value is UObject obj) 68 | { 69 | foreach (var kp in obj.properties.Values) 70 | ReplaceGUID(kp, map); 71 | } 72 | else if (property.value is UArray arr) 73 | { 74 | foreach (var item in arr.items) 75 | ReplaceGUID(new UProperty(string.Empty, item), map); 76 | } 77 | } 78 | 79 | 80 | } 81 | #endif 82 | } 83 | -------------------------------------------------------------------------------- /Runtime/Utilities/Circle.cs: -------------------------------------------------------------------------------- 1 | using Lachee.Attributes; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace Lachee.Utilities 7 | { 8 | [RequireComponent(typeof(LineRenderer))] 9 | [ExecuteInEditMode] 10 | public class Circle : MonoBehaviour 11 | { 12 | public enum Mode 13 | { 14 | XY, 15 | XZ, 16 | ZY, 17 | } 18 | 19 | 20 | /// Current line renderer 21 | [Auto] 22 | public LineRenderer lineRenderer; 23 | 24 | [Tooltip("Radius of the circle")] 25 | [SerializeField] 26 | private float _radius = 0.5f; 27 | public float radius { get { return _radius; } set { _radius = value; UpdatePoints(); } } 28 | 29 | [Tooltip("How many points on the circle")] 30 | [Range(3, 360)] 31 | [SerializeField] 32 | private int _points = 16; 33 | public int points { get { return _points; } set { _points = value; UpdatePoints(); } } 34 | 35 | [Tooltip("Offset of the circle")] 36 | [SerializeField] 37 | private Vector3 _offset = Vector3.zero; 38 | public Vector3 offset { get { return _offset; } set { _offset = value; UpdatePoints(); } } 39 | 40 | [Tooltip("Orientation of the circle")] 41 | [SerializeField] 42 | private Mode _mode = Mode.XZ; 43 | public Mode mode { get { return _mode; } set { _mode = value; UpdatePoints(); } } 44 | 45 | private void Start() 46 | { 47 | UpdatePoints(); 48 | } 49 | 50 | #if UNITY_EDITOR 51 | private void Update() { 52 | if (!Application.isPlaying) 53 | UpdatePoints(); 54 | } 55 | #endif 56 | 57 | [ContextMenu("Update Points")] 58 | public void UpdatePoints() 59 | { 60 | if (lineRenderer == null) 61 | return; 62 | 63 | lineRenderer.positionCount = _points; 64 | lineRenderer.useWorldSpace = false; 65 | lineRenderer.loop = true; 66 | 67 | float angleOffset = 360f / _points; 68 | for (int i = 0; i < _points; i++) 69 | { 70 | float radians = Mathf.Deg2Rad * (angleOffset * i); 71 | float x = _radius * Mathf.Cos(radians); 72 | float y = _radius * Mathf.Sin(radians); 73 | 74 | Vector3 vector; 75 | switch(_mode) 76 | { 77 | case Mode.XY: 78 | vector = new Vector3(x, y, 0); 79 | break; 80 | 81 | default: 82 | case Mode.XZ: 83 | vector = new Vector3(x, 0, y); 84 | break; 85 | 86 | case Mode.ZY: 87 | vector = new Vector3(0, x, y); 88 | break; 89 | } 90 | 91 | lineRenderer.SetPosition(i, vector + _offset); 92 | } 93 | } 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /Editor/Icons/Icon.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.IO; 6 | 7 | namespace Lachee.Editor.Icons 8 | { 9 | internal static class Icon 10 | { 11 | private const string BASE_PATH = "Packages/com.lachee.utilities/Editor/Icons/"; 12 | private static Dictionary _cache = new Dictionary(6); 13 | 14 | public static Texture equals => Load("equals_100"); 15 | public static Texture link => Load("auto_32"); 16 | public static Texture link_sm => Load("auto_16"); 17 | public static Texture rotate => Load("rotate"); 18 | public static Texture singleton => Load("singleton"); 19 | 20 | public static Texture ristBar => Load("ristbar"); 21 | public static Texture @namespace => Load("NamespaceConfigurationIcon"); 22 | 23 | /// 24 | /// Gets a texture and stores it in a cache if requried 25 | /// 26 | /// 27 | /// 28 | /// 29 | public static Texture Load(string name, bool recache = false) 30 | { 31 | //Check the cache 32 | if (!recache && _cache.TryGetValue(name, out var t)) 33 | return t; 34 | 35 | 36 | //Load the file 37 | string filePath = BASE_PATH + name; 38 | if (string.IsNullOrEmpty(Path.GetExtension(filePath))) 39 | filePath += ".png"; 40 | 41 | if (!File.Exists(filePath)) 42 | { 43 | Debug.LogError("The icon " + name + " does not exist!"); 44 | return null; 45 | } 46 | 47 | //Load the texture and store 48 | Texture texture = AssetDatabase.LoadAssetAtPath(filePath); 49 | _cache[name] = texture; 50 | return texture; 51 | } 52 | 53 | /// 54 | /// Draws a preview of a sprite 55 | /// 56 | /// 57 | /// 58 | public static void DrawSpritePreview(Rect position, Sprite sprite) 59 | { 60 | Vector2 fullSize = new Vector2(sprite.texture.width, sprite.texture.height); 61 | Vector2 size = new Vector2(sprite.textureRect.width, sprite.textureRect.height); 62 | 63 | Rect coords = sprite.textureRect; 64 | coords.x /= fullSize.x; 65 | coords.width /= fullSize.x; 66 | coords.y /= fullSize.y; 67 | coords.height /= fullSize.y; 68 | 69 | Vector2 ratio; 70 | ratio.x = position.width / size.x; 71 | ratio.y = position.height / size.y; 72 | float minRatio = Mathf.Min(ratio.x, ratio.y); 73 | 74 | Vector2 center = position.center; 75 | position.width = size.x * minRatio; 76 | position.height = size.y * minRatio; 77 | position.center = center; 78 | 79 | GUI.DrawTextureWithTexCoords(position, sprite.texture, coords); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Runtime/Utilities/Mathl.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Utilities 6 | { 7 | /// 8 | /// Wet Maths a.k.a MathLake MathLachee, or MathLoony... however you want it. 9 | /// Bunch of static maths functions that are useful, like Cyclic Modulo 10 | /// 11 | public static class Mathl 12 | { 13 | /// 14 | /// Maps a value from it a range to a new range 15 | /// 16 | /// the value to map 17 | /// the minimum the value can be 18 | /// the maximum the value can be 19 | /// the value minimum gets mapped into 20 | /// the value maximum gets mapped into 21 | /// value mapped from toMin to toMax 22 | public static float Map(float value, float fromMin, float fromMax, float toMin, float toMax) { 23 | return ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin; 24 | } 25 | 26 | /// 27 | /// Cyclic modulo 28 | /// Thanks SaroVati :3 29 | /// 30 | /// 31 | /// 32 | /// 33 | public static int Mod(int x, int m) { 34 | return (x % m + m) % m; 35 | } 36 | 37 | /// 38 | /// Counts the number of bits set in the bitflag. 39 | /// 40 | /// The bitflag 41 | /// 42 | public static int BitsSet(int i) { 43 | i = i - ((i >> 1) & 0x55555555); 44 | i = (i & 0x33333333) + ((i >> 2) & 0x33333333); 45 | return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; 46 | } 47 | 48 | /// 49 | /// Returns true if the other rectangle overlaps this rectangle. 50 | /// 51 | /// 52 | /// 53 | /// The inner overlap rectangle 54 | /// 55 | public static bool Overlaps(this Rect self, Rect other, out Rect overlap) 56 | { 57 | if (!self.Overlaps(other)) 58 | { 59 | overlap = other; 60 | return false; 61 | } 62 | 63 | float left = Mathf.Max(self.xMin, other.xMin); 64 | float width = Mathf.Min(self.xMax, other.xMax) - left; 65 | float top = Mathf.Max(self.yMin, other.yMin); 66 | float height = Mathf.Min(self.yMax, other.yMax) - top; 67 | overlap = new Rect(left, top, width, height); 68 | return true; 69 | } 70 | 71 | /// 72 | /// Extrudes the vector a distance away from the center 73 | /// 74 | /// The starting vector 75 | /// The center to extrude away from 76 | /// The distance to exture 77 | /// 78 | public static Vector3 Extrude(this Vector3 vector, Vector3 center, float distance) { 79 | if (distance == 0) return vector; 80 | Vector3 norm = (vector-center).normalized; 81 | return vector + (norm * distance); 82 | } 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /Editor/Attributes/AutoAttributeDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | namespace Lachee.Attributes.Editor 8 | { 9 | [CustomPropertyDrawer(typeof(AutoAttribute))] 10 | public class AutoAttributeDrawer : PropertyDrawer 11 | { 12 | const float ICON_LABEL_OFFSET = 1.5f; 13 | 14 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 15 | { 16 | try 17 | { 18 | 19 | var attr = attribute as AutoAttribute; 20 | // Null, so lets assign it 21 | if (AutoAttributeEditor.AutoRefreshInspector) 22 | AutoAttributeEditor.ApplyAttributeToSerializedProperty(property, attr); 23 | 24 | var optionalError = AutoAttributeEditor.Validate(property); 25 | 26 | if (!attr.Hidden || optionalError.HasValue) 27 | PropertyGUI(position, property, label); 28 | 29 | // If we have an error, render the error stuff 30 | if (optionalError is AutoAttributeEditor.Error error) 31 | { 32 | var baseHeight = base.GetPropertyHeight(property, label); 33 | 34 | Rect errorBox = new Rect(position.x + EditorGUIUtility.labelWidth + 1f, position.y + baseHeight + 1, position.width - EditorGUIUtility.labelWidth, position.height - baseHeight - 1); 35 | EditorGUI.HelpBox(errorBox, error.message, error.blocks ? MessageType.Error : MessageType.Warning); 36 | } 37 | } 38 | catch(System.Exception e) 39 | { 40 | EditorGUI.HelpBox(position, e.Message, MessageType.Error); 41 | Debug.Log(e); 42 | } 43 | } 44 | 45 | private void PropertyGUI(Rect position, SerializedProperty property, GUIContent label) 46 | { 47 | try 48 | { 49 | // Ensure regardless of height we still have a regular sized box 50 | position.height = base.GetPropertyHeight(property, label); 51 | 52 | // Not hidden, lets just display it 53 | var iconLabel = new GUIContent(AutoAttributeEditor.IconAuto_16); 54 | iconLabel.tooltip = "Automatically Linked Component"; 55 | Rect iconBox = new Rect(position.x + EditorGUIUtility.labelWidth - position.height - 1.5f, position.y + 1.5f, position.height - 3, position.height - 3); 56 | EditorGUI.LabelField(iconBox, iconLabel); 57 | 58 | EditorGUI.PropertyField(position, property, label); 59 | GUI.color = Color.white; 60 | 61 | } 62 | catch (System.Exception e) 63 | { 64 | EditorGUI.HelpBox(position, e.Message, MessageType.Error); 65 | Debug.Log(e); 66 | } 67 | } 68 | 69 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 70 | { 71 | try 72 | { 73 | if (AutoAttributeEditor.Validate(property).HasValue) 74 | return base.GetPropertyHeight(property, label) + 20; 75 | 76 | var attr = attribute as AutoAttribute; 77 | return attr.Hidden ? 0 : base.GetPropertyHeight(property, label); 78 | } 79 | catch(System.Exception e) 80 | { 81 | Debug.LogError("Failed to determine the best high for an auto attribute\n" + e.Message); 82 | return EditorGUIUtility.singleLineHeight; 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Editor/Icons/ristbar.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 070e41d379767d34aa78e18e6906a539 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 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 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMasterTextureLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 0 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 0 41 | wrapV: 0 42 | wrapW: 0 43 | nPOTScale: 1 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 0 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 2 55 | alphaIsTransparency: 0 56 | spriteTessellationDetail: -1 57 | textureType: 0 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | platformSettings: 69 | - serializedVersion: 3 70 | buildTarget: DefaultTexturePlatform 71 | maxTextureSize: 2048 72 | resizeAlgorithm: 0 73 | textureFormat: -1 74 | textureCompression: 1 75 | compressionQuality: 50 76 | crunchedCompression: 0 77 | allowsAlphaSplitting: 0 78 | overridden: 0 79 | androidETC2FallbackOverride: 0 80 | forceMaximumCompressionQuality_BC6H_BC7: 0 81 | - serializedVersion: 3 82 | buildTarget: Standalone 83 | maxTextureSize: 2048 84 | resizeAlgorithm: 0 85 | textureFormat: -1 86 | textureCompression: 1 87 | compressionQuality: 50 88 | crunchedCompression: 0 89 | allowsAlphaSplitting: 0 90 | overridden: 0 91 | androidETC2FallbackOverride: 0 92 | forceMaximumCompressionQuality_BC6H_BC7: 0 93 | - serializedVersion: 3 94 | buildTarget: Server 95 | maxTextureSize: 2048 96 | resizeAlgorithm: 0 97 | textureFormat: -1 98 | textureCompression: 1 99 | compressionQuality: 50 100 | crunchedCompression: 0 101 | allowsAlphaSplitting: 0 102 | overridden: 0 103 | androidETC2FallbackOverride: 0 104 | forceMaximumCompressionQuality_BC6H_BC7: 0 105 | - serializedVersion: 3 106 | buildTarget: WebGL 107 | maxTextureSize: 2048 108 | resizeAlgorithm: 0 109 | textureFormat: -1 110 | textureCompression: 1 111 | compressionQuality: 50 112 | crunchedCompression: 0 113 | allowsAlphaSplitting: 0 114 | overridden: 0 115 | androidETC2FallbackOverride: 0 116 | forceMaximumCompressionQuality_BC6H_BC7: 0 117 | spriteSheet: 118 | serializedVersion: 2 119 | sprites: [] 120 | outline: [] 121 | physicsShape: [] 122 | bones: [] 123 | spriteID: 124 | internalID: 0 125 | vertices: [] 126 | indices: 127 | edges: [] 128 | weights: [] 129 | secondaryTextures: [] 130 | nameFileIdTable: {} 131 | spritePackingTag: 132 | pSDRemoveMatte: 0 133 | userData: 134 | assetBundleName: 135 | assetBundleVariant: 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 21 | 22 |
4 | 5 | 7 |

Lachee's Utilities

8 |

9 | 10 | GitHub package.json version 11 | 12 |

13 |

14 | This package contains a collection of useful classes and tools that I have personally used throughout my games. 15 | Originating from Party Crashers, I have been slowly building and involving this kit, and now with Unity Package Manager being "somewhat" stable, I decided to make a github repository so I can better track the changes and synchronise the numerous versions I have. 16 |

17 |

18 | Since it is just a "collection of scripts", there isn't much in the ways of a manual or a theme for the package other than "hey thats useful". Since it is all under MIT, you are free to simply extract just the scripts you need, there is no dependencies amongst the files unless explicitly stated in the top of the file (ie: some of the custom editors). 19 |

20 |
23 | 24 | # Usage 25 | Since this is just a folder of scripts, you can use it how you need it. Check out the documentation for more information. 26 | 27 | [https://lachee.github.io/unity-utilities/](https://lachee.github.io/unity-utilities/) 28 | 29 | # Installation 30 | #### OpenUPM 31 | The [openupm registry](https://openupm.com) is a open source package manager for Unity and provides the [openupm-cli](https://github.com/openupm/openupm-cli) to manage your dependencies. 32 | ``` 33 | openupm add com.lachee.unity-utilities 34 | ``` 35 | 36 | #### Manual UPM GitHub package.json version 37 | Use the Unity Package Manager to add a git package. Adding the git to your UPM will limit updates as Unity will not track versioning on git projects (even though they totally could with tags). 38 | 1. Open the Unity Package Manager and `Add Package by git URL...` 39 | 2. `https://github.com/Lachee/unity-utilities.git ` 40 | 41 | For local editable versions, manually clone the repo into your package folder. Note the exact spelling on destination name. 42 | 1. `git clone https://github.com/Lachee/unity-utilities.git Packages/com.lachee.utilities` 43 | 44 | #### Unity Package 45 | Go old school and download the Unity Package and import it into your project. 46 | 1. Download the `.unitypackage` from the [Releases](releases) or via the last run `Create Release` action. 47 | 2. Import that package into your Unity3D 48 | 49 | # TODO 50 | List of things I wish to implement: 51 | 52 | - More Surrogates for Binary Formatter 53 | - My PlayerPrefs from Cross-Platform as it supports Serialization / Deserialization 54 | - Fix to my Automatic Namespacer with better support for rules 55 | - I should rewrite this 56 | - Configuration panel for stuff? Probably not required 57 | - Implement https://forum.unity.com/threads/detecting-textmesh-pro.755501/ so i can add Input features 58 | - Asset Bin: Allows you to quickly grab and store assets for building stuff 59 | - Right Click - Jump to Definition 60 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 📦 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | env: 9 | package_path: "lachee-utilities.unitypackage" 10 | 11 | jobs: 12 | # build the packages 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | feature: 18 | - name: All Utilities ( complete set ) 19 | package: lachee-utilities-complete.unitypackage 20 | assets: [ "**/*.cs"] 21 | exclude: [ "Documentation", "tools", ".*" ] 22 | - name: Auto Attribute 23 | package: lachee-utilities-only-auto-attributes.unitypackage 24 | assets: [ "Runtime/Attributes/**/AutoAttribute*.cs", "Editor/Attributes/**/AutoAttribute*.cs" ] 25 | exclude: [ ] 26 | - name: Singletons 27 | package: lachee-utilities-only-singletons.unitypackage 28 | assets: [ "Runtime/Utilities/Singleton.cs" ] 29 | exclude: [ ] 30 | - name: Auto Namespace 31 | package: lachee-utilities-only-auto-namespace.unitypackage 32 | assets: [ "Editor/Tools/Namespace*.cs", "Editor/Icons/Namespace*.png", "Editor/Tools/EOLConversion.cs" ] 33 | - name: End Of Line Converter 34 | package: lachee-utilities-only-eol-converter.unitypackage 35 | assets: [ "Editor/Tools/EOLConversion.cs" ] 36 | exclude: [ ] 37 | - name: UYAML 38 | package: lachee-utilities-uyaml.unitypackage 39 | assets: [ "Runtime/UYAML/*.cs" ] 40 | exclude: [ ] 41 | steps: 42 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 43 | - uses: actions/checkout@v3 44 | - uses: actions/setup-dotnet@v3 45 | with: 46 | dotnet-version: '3.1.x' 47 | 48 | # Install the packager 49 | - name: Install Unity Packager 50 | run: | 51 | git clone https://github.com/Lachee/Unity-Package-Exporter.git tools/unity-package-exporter 52 | dotnet publish -c Release -o tools tools/unity-package-exporter/UnityPackageExporter 53 | 54 | # Pack the assets 55 | - name: Package ${{matrix.feature.name}} 56 | run: | 57 | echo "Creating package ${{matrix.feature.name}} at ${{matrix.feature.package}}" 58 | dotnet tools/UnityPackageExporter.dll \ 59 | ./ \ 60 | ${{matrix.feature.package}} \ 61 | --sub-folder "Lachee/Utilities" \ 62 | --exclude "${{ join(matrix.feature.exclude, '" --exclude "')}}" \ 63 | --assets "${{ join(matrix.feature.assets, '" --assets "')}}" \ 64 | --assets "Editor/Tools/HelpContext.cs" \ 65 | -r . 66 | 67 | # Upload artifact 68 | - name: Upload Artifact 69 | uses: actions/upload-artifact@v3.0.0 70 | with: 71 | name: ${{matrix.feature.name}} 72 | path: ${{matrix.feature.package}} 73 | 74 | # Tag the build 75 | tag: 76 | runs-on: ubuntu-latest 77 | steps: 78 | - uses: actions/checkout@v2 79 | - uses: Klemensas/action-autotag@stable 80 | id: auto-tag 81 | with: 82 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 83 | tag_prefix: "v" 84 | outputs: 85 | tag: ${{ steps.auto-tag.outputs.tagname }} 86 | 87 | # Update the release 88 | release: 89 | runs-on: ubuntu-latest 90 | needs: [ build, tag ] 91 | if: ${{ startsWith(needs.tag.outputs.tag, 'v') }} 92 | steps: 93 | - uses: actions/checkout@v3 94 | 95 | - uses: actions/download-artifact@v3 96 | with: 97 | path: artifacts 98 | 99 | - uses: "marvinpinto/action-automatic-releases@latest" 100 | with: 101 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 102 | automatic_release_tag: ${{ needs.tag.outputs.tag }} 103 | prerelease: true 104 | title: Release ${{ needs.tag.outputs.tag }} 105 | files: artifacts/**/*.unitypackage 106 | -------------------------------------------------------------------------------- /Editor/Attributes/AutoAttributeWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Lachee.Attributes.Editor 5 | { 6 | public class AutoAttributeWindow : EditorWindow 7 | { 8 | private static AutoAttributeWindow _instance; 9 | public static AutoAttributeWindow Instance => _instance; 10 | 11 | private Vector2 scrollPosition = Vector2.zero; 12 | 13 | [MenuItem("Tools/Lachee/Auto Errors")] 14 | public static void ShowWindow() 15 | { 16 | if (!_instance) 17 | { 18 | _instance = EditorWindow.CreateWindow(new System.Type[] { System.Type.GetType("UnityEditor.ConsoleWindow,UnityEditor.dll") }); 19 | _instance.titleContent = new GUIContent("Auto Errors"); 20 | } 21 | _instance.Focus(); 22 | } 23 | 24 | private void OnEnable() 25 | { 26 | // Update all the attributes, processing their errors again 27 | AutoAttributeEditor.CheckAttributes(); 28 | } 29 | 30 | private void OnHierarchyChange() 31 | { 32 | Repaint(); 33 | } 34 | 35 | public void OnGUI() 36 | { 37 | EditorGUILayout.BeginVertical(); 38 | { 39 | // Draw the settings 40 | EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); 41 | 42 | EditorGUILayout.BeginHorizontal(); 43 | { 44 | 45 | AutoAttributeEditor.PreventPlayMode = EditorGUILayout.Toggle("Block PlayMode", AutoAttributeEditor.PreventPlayMode); 46 | AutoAttributeEditor.AutoRefreshInspector = EditorGUILayout.Toggle("Always Refresh Inspected", AutoAttributeEditor.AutoRefreshInspector); 47 | } 48 | EditorGUILayout.EndHorizontal(); 49 | 50 | if (GUILayout.Button("Manually Scan Attributes", GUILayout.MaxWidth(200f))) 51 | AutoAttributeEditor.CheckAttributes(); 52 | 53 | EditorGUILayout.Space(10f); 54 | 55 | // Draw the errors 56 | EditorGUILayout.LabelField("Errors", EditorStyles.boldLabel); 57 | scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); 58 | EditorGUILayout.BeginVertical(); 59 | foreach (var error in AutoAttributeEditor.Errors) 60 | { 61 | DrawErrorLayout(error); 62 | EditorGUILayout.Space(10f); 63 | } 64 | EditorGUILayout.EndVertical(); 65 | EditorGUILayout.EndScrollView(); 66 | } 67 | EditorGUILayout.EndVertical(); 68 | } 69 | 70 | private void DrawErrorLayout(AutoAttributeEditor.ObjectErrors errors) 71 | { 72 | SerializedObject serializedObject = new SerializedObject(errors.Component); 73 | var gameObject = (errors.Component as Component).gameObject; 74 | 75 | EditorGUILayout.BeginHorizontal(); 76 | EditorGUILayout.ObjectField(gameObject.name, errors.Component, errors.Component.GetType(), true); 77 | if (GUILayout.Button("Reveal in Inspector", GUILayout.Width(175f))) 78 | Selection.activeObject = errors.Component; 79 | EditorGUILayout.EndHorizontal(); 80 | 81 | GUILayout.BeginHorizontal(); 82 | { 83 | GUILayout.Space(EditorGUIUtility.labelWidth + 5f); 84 | EditorGUILayout.BeginVertical(); 85 | { 86 | var originalLabelWidth = EditorGUIUtility.labelWidth; 87 | EditorGUIUtility.labelWidth = 200f; 88 | foreach (var kp in errors) 89 | { 90 | var path = kp.Key; 91 | EditorGUILayout.PropertyField(serializedObject.FindProperty(path.propertyPath)); 92 | } 93 | EditorGUIUtility.labelWidth = originalLabelWidth; 94 | } 95 | EditorGUILayout.EndVertical(); 96 | } 97 | EditorGUILayout.EndHorizontal(); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /Editor/Tools/EOLConversion.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | using UnityEditor; 4 | using System.IO; 5 | 6 | namespace Lachee.Tools.Editor 7 | { 8 | /// 9 | /// Provides tools to convert line endings 10 | /// 11 | public class EOLConversion : UnityEditor.AssetModificationProcessor 12 | { 13 | public const string PREFS_PREFERED = "prefered_eol"; 14 | public const string PREFS_PROCESS = "process_eol"; 15 | 16 | [MenuItem("Tools/Lachee/EOL Conversion/Windows")] 17 | private static void ConvertToWindows() 18 | { 19 | EditorPrefs.SetString(PREFS_PREFERED, "\r\n"); 20 | #if UNITY_2018_1_OR_NEWER 21 | EditorSettings.lineEndingsForNewScripts = LineEndingsMode.Windows; 22 | #endif 23 | Convert("\r\n"); 24 | } 25 | 26 | 27 | [MenuItem("Tools/Lachee/EOL Conversion/Unix")] 28 | private static void ConvertToUnix() 29 | { 30 | EditorPrefs.SetString(PREFS_PREFERED, "\n"); 31 | #if UNITY_2018_1_OR_NEWER 32 | EditorSettings.lineEndingsForNewScripts = LineEndingsMode.Unix; 33 | #endif 34 | Convert("\n"); 35 | } 36 | 37 | [MenuItem("Tools/Lachee/EOL Conversion/Automaticly Process")] 38 | private static void ToggleProcessing() 39 | { 40 | bool auto = EditorPrefs.GetBool(PREFS_PROCESS, true); 41 | EditorPrefs.SetBool(PREFS_PROCESS, !auto); 42 | } 43 | 44 | [MenuItem("Tools/Lachee/EOL Conversion/Automaticly Process", true)] 45 | private static bool ToogleProcessingValidation() 46 | { 47 | bool auto = EditorPrefs.GetBool(PREFS_PROCESS, true); 48 | Menu.SetChecked("Tools/EOL Conversion/Automaticly Process", auto); 49 | return true; 50 | } 51 | 52 | /// 53 | /// This gets called for every .meta file created by the Editor. 54 | /// 55 | public static void OnWillCreateAsset(string path) 56 | { 57 | bool auto = EditorPrefs.GetBool(PREFS_PROCESS, true); 58 | if (!auto) return; 59 | 60 | path = path.Replace(".meta", string.Empty); 61 | if (!path.EndsWith(".cs")) 62 | return; 63 | 64 | if (!EditorPrefs.HasKey(PREFS_PREFERED)) 65 | return; 66 | 67 | string lineEnding = EditorPrefs.GetString(PREFS_PREFERED); 68 | if (ConvertFile(path, lineEnding)) 69 | AssetDatabase.Refresh(); 70 | } 71 | 72 | /// Converts all the assets and returns a list of files that were modified 73 | public static string[] Convert(string lineEnding) 74 | { 75 | List assetsConverted = new List(); 76 | string[] assetPaths = AssetDatabase.GetAllAssetPaths(); 77 | int progress = 0; 78 | 79 | foreach (string assetPath in assetPaths) 80 | { 81 | EditorUtility.DisplayProgressBar("Converting Line Ending", assetPath, (progress++ / (float)assetPaths.Length)); 82 | if (ConvertFile(assetPath, lineEnding)) 83 | assetsConverted.Add(assetPath); 84 | } 85 | 86 | EditorUtility.ClearProgressBar(); 87 | 88 | UnityEngine.Debug.Log($"Converted {assetsConverted.Count} files"); 89 | return assetsConverted.ToArray(); 90 | } 91 | 92 | /// Converts a single file's line ending 93 | public static bool ConvertFile(string path) 94 | => ConvertFile(path, EditorPrefs.GetString(PREFS_PREFERED, "\r\n")); 95 | 96 | /// Converts a single file's line ending 97 | public static bool ConvertFile(string path, string lineEnding) 98 | { 99 | if (!path.EndsWith(".cs") || path.StartsWith("Packages/")) 100 | return false; 101 | 102 | string content = File.ReadAllText(path); 103 | string contentNew = Regex.Replace(content, @"\r\n|\n\r|\n|\r", lineEnding); 104 | 105 | if (content != contentNew) 106 | { 107 | File.WriteAllText(path, contentNew); 108 | return true; 109 | } 110 | 111 | return false; 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /Editor/Attributes/SlideDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Lachee.Attributes.Editor 5 | { 6 | [CustomPropertyDrawer(typeof(SlideAttribute))] 7 | public class SlideDrawer : PropertyDrawer 8 | { 9 | const float miniLabelVerticalOffset = -7; 10 | 11 | static GUIStyle miniLabelStyle; 12 | static SlideDrawer() 13 | { 14 | miniLabelStyle = new GUIStyle(EditorStyles.miniLabel); 15 | } 16 | 17 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 18 | { 19 | // Lock the position to the bottom 20 | position.y = position.y + position.height - EditorGUIUtility.singleLineHeight; 21 | 22 | SlideAttribute attr = (SlideAttribute)attribute; 23 | 24 | // Draw the left and right 25 | if (attr.LeftLabel != null) 26 | { 27 | miniLabelStyle.alignment = TextAnchor.UpperLeft; 28 | EditorGUI.LabelField(new Rect(position.x + EditorGUIUtility.labelWidth, position.y + miniLabelVerticalOffset, position.width, position.height), attr.LeftLabel, miniLabelStyle); 29 | } 30 | 31 | //style.alignment = TextAnchor.LowerRight; 32 | if (attr.RightLabel != null) 33 | { 34 | float padding = property.propertyType == SerializedPropertyType.Float || property.propertyType == SerializedPropertyType.Integer ? -EditorGUIUtility.fieldWidth - 5 : 0; 35 | miniLabelStyle.alignment = TextAnchor.UpperRight; 36 | EditorGUI.LabelField(new Rect(position.x + EditorGUIUtility.labelWidth, position.y + miniLabelVerticalOffset, position.width - EditorGUIUtility.labelWidth + padding, position.height), attr.RightLabel, miniLabelStyle); 37 | } 38 | 39 | // Draw the slider 40 | Rect sliderPosition = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); 41 | switch (property.propertyType) 42 | { 43 | case SerializedPropertyType.Float: 44 | EditorGUI.Slider(sliderPosition, property, attr.Min, attr.Max, label); 45 | break; 46 | case SerializedPropertyType.Integer: 47 | EditorGUI.IntSlider(sliderPosition, property, (int) attr.Min, (int) attr.Max, label); 48 | break; 49 | case SerializedPropertyType.Vector2: 50 | case SerializedPropertyType.Vector2Int: 51 | MinMaxSlider(sliderPosition, property, attr.Min, attr.Max, label); 52 | break; 53 | default: 54 | EditorGUI.LabelField(position, label, new GUIContent("Slider must be of type float, int, Vector2, or Vector2Int")); 55 | return; 56 | } 57 | 58 | } 59 | 60 | private static void MinMaxSlider(Rect position, SerializedProperty property, float min, float max, GUIContent label) 61 | { 62 | //TODO: Look at how unity draws its MinMaxSlider attribute 63 | 64 | float minValue = 0; 65 | float maxValue = 0; 66 | 67 | if (property.propertyType == SerializedPropertyType.Vector2) 68 | { 69 | minValue = property.vector2Value.x; 70 | maxValue = property.vector2Value.y; 71 | EditorGUI.MinMaxSlider(position, label, ref minValue, ref maxValue, min, max); 72 | property.vector2Value = new Vector2(minValue, maxValue); 73 | } 74 | else if (property.propertyType == SerializedPropertyType.Vector2Int) 75 | { 76 | minValue = property.vector2IntValue.x; 77 | maxValue = property.vector2IntValue.y; 78 | EditorGUI.MinMaxSlider(position, label, ref minValue, ref maxValue, min, max); 79 | property.vector2IntValue = new Vector2Int(Mathf.RoundToInt(minValue), Mathf.RoundToInt(maxValue)); 80 | } 81 | else 82 | { 83 | throw new System.ArgumentException("The property must be a vector2 type"); 84 | } 85 | } 86 | 87 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 88 | { 89 | float height = base.GetPropertyHeight(property, label); 90 | 91 | SlideAttribute attr = attribute as SlideAttribute; 92 | if (attr != null && (attr.LeftLabel != null || attr.RightLabel != null)) 93 | height += -miniLabelVerticalOffset; 94 | 95 | return height; 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /Runtime/Behaviours/PerCameraSettings.cs: -------------------------------------------------------------------------------- 1 | using Lachee.Attributes; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace Lachee.Behaviours 7 | { 8 | [RequireComponent(typeof(Camera))] 9 | [ExecuteInEditMode] 10 | public class PerCameraSettings : MonoBehaviour 11 | { 12 | [System.Serializable] 13 | public sealed class RenderSettingsState 14 | { 15 | private RenderSettingsState _previousState; 16 | 17 | #region Fog 18 | [Header("Fog Settings")] 19 | [Toggle("#Inherit", "Inherit", true)] public bool fog; 20 | [HideInInspector] public bool fogInherit = true; 21 | 22 | [Toggle("#Inherit", "Inherit ", true)] public Color fogColor; 23 | [HideInInspector] public bool fogColorInherit = true; 24 | 25 | [Toggle("#Inherit", "Inherit ", true)] public FogMode fogMode; 26 | [HideInInspector] public bool fogModeInherit = true; 27 | 28 | [Toggle("#Inherit", "Inherit ", true)] public float fogDensity; 29 | [HideInInspector] public bool fogDensityInherit = true; 30 | 31 | [Toggle("#Inherit", "Inherit ", true)] public float fogStartDistance; 32 | [HideInInspector] public bool fogStartDistanceInherit = true; 33 | 34 | [Toggle("#Inherit", "Inherit ", true)] public float fogEndDistance; 35 | [HideInInspector] public bool fogEndDistanceInherit = true; 36 | #endregion 37 | 38 | 39 | /// Creates a restore point for all the settings 40 | public void CreateState() { 41 | _previousState = FromCurrentRenderSettings(); 42 | } 43 | 44 | /// Applies the current settings 45 | public void Apply() 46 | => Apply(false); 47 | 48 | /// Reverts the settings by forcefully reverting the state 49 | public void Revert() 50 | { 51 | _previousState.Apply(true); 52 | } 53 | 54 | private void Apply(bool force) 55 | { 56 | if (force || !fogInherit) RenderSettings.fog = fog; 57 | if (force || !fogColorInherit) RenderSettings.fogColor = fogColor; 58 | if (force || !fogModeInherit) RenderSettings.fogMode = fogMode; 59 | if (force || !fogDensityInherit) RenderSettings.fogDensity = fogDensity; 60 | if (force || !fogStartDistanceInherit) RenderSettings.fogStartDistance = fogStartDistance; 61 | if (force || !fogEndDistanceInherit) RenderSettings.fogEndDistance = fogEndDistance; 62 | } 63 | 64 | public static RenderSettingsState FromCurrentRenderSettings() 65 | { 66 | return new RenderSettingsState() { 67 | fog = RenderSettings.fog, 68 | fogColor = RenderSettings.fogColor, 69 | fogMode = RenderSettings.fogMode, 70 | fogDensity = RenderSettings.fogDensity, 71 | fogStartDistance = RenderSettings.fogStartDistance, 72 | fogEndDistance = RenderSettings.fogEndDistance 73 | }; 74 | } 75 | } 76 | 77 | 78 | [Auto, SerializeField] 79 | private new Camera camera; 80 | 81 | public bool active = true; 82 | public RenderSettingsState renderSettings; 83 | 84 | [System.Serializable] 85 | public class GlobalShaderProperty 86 | { 87 | public string name = "_Global_Variable"; 88 | public float value = 1f; 89 | 90 | public bool revert = false; 91 | public float revertValue = 0f; 92 | 93 | } 94 | public GlobalShaderProperty[] properties; 95 | 96 | private void OnPreRender() 97 | { 98 | if (!active) return; 99 | #if UNITY_EDITOR && false 100 | if (Application.isPlaying) 101 | #endif 102 | { 103 | renderSettings.CreateState(); 104 | renderSettings.Apply(); 105 | } 106 | 107 | foreach(var property in properties) 108 | { 109 | Shader.SetGlobalFloat(property.name, property.value); 110 | } 111 | } 112 | 113 | private void OnPostRender() 114 | { 115 | if (!active) return; 116 | #if UNITY_EDITOR && false 117 | if (Application.isPlaying) 118 | #endif 119 | { 120 | renderSettings.Revert(); 121 | } 122 | foreach (var property in properties) 123 | { 124 | if (!property.revert) continue; 125 | Shader.SetGlobalFloat(property.name, property.revertValue); 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Editor/Utilities/UnityEventDrawer.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_2020_1_OR_NEWER 2 | using UnityEditor; 3 | using UnityEngine; 4 | using UnityEngine.Events; 5 | using System.Reflection; 6 | using UnityEditorInternal; 7 | 8 | namespace Lachee.Utilities.Editor 9 | { 10 | [CustomPropertyDrawer(typeof(UnityEventBase), true)] 11 | public class UnityEventDrawer : UnityEditorInternal.UnityEventDrawer 12 | { 13 | #region Private Functions i steal from UnityEventDrawerer 14 | private static readonly FieldInfo fi_reoderableList; 15 | private static readonly FieldInfo fi_dummyEvent; 16 | private static readonly FieldInfo fi_text; 17 | private static readonly MethodInfo mi_RestoreState; 18 | private static readonly MethodInfo mi_GetDummyEvent; 19 | 20 | static UnityEventDrawer() 21 | { 22 | var T = typeof(UnityEditorInternal.UnityEventDrawer); 23 | fi_reoderableList = T.GetField("m_ReorderableList", BindingFlags.NonPublic | BindingFlags.Instance); 24 | fi_dummyEvent = T.GetField("m_DummyEvent", BindingFlags.NonPublic | BindingFlags.Instance); 25 | fi_text = T.GetField("m_Text", BindingFlags.NonPublic | BindingFlags.Instance); 26 | mi_GetDummyEvent = T.GetMethod("GetDummyEvent", BindingFlags.NonPublic | BindingFlags.Static); 27 | mi_RestoreState = T.GetMethod("RestoreState", BindingFlags.NonPublic | BindingFlags.Instance); 28 | } 29 | 30 | private static UnityEventBase GetDummyEvent(SerializedProperty prop) 31 | => (UnityEventBase)mi_GetDummyEvent.Invoke(null, new object[] { prop }); 32 | 33 | private ReorderableList reorderableList 34 | { 35 | get => (ReorderableList)fi_reoderableList.GetValue(this); 36 | } 37 | private UnityEventBase dummyEvent 38 | { 39 | get => (UnityEventBase)fi_dummyEvent.GetValue(this); 40 | set => fi_dummyEvent.SetValue(this, value); 41 | } 42 | private string text 43 | { 44 | get => (string)fi_text.GetValue(this); 45 | set => fi_text.SetValue(this, value); 46 | } 47 | private State RestoreState(SerializedProperty property) 48 | => (State)mi_RestoreState.Invoke(this, new[] { property }); 49 | #endregion 50 | 51 | private readonly GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add new event listener"); 52 | private readonly GUIStyle headerBackground = "LODSliderBG"; 53 | private readonly GUIStyle preButton = "RL FooterButton"; 54 | private readonly Color headerColor = new Color(0.85f, 0.85f, 0.85f); 55 | 56 | private bool? _isFolded; 57 | private bool isFolded 58 | { 59 | get => _isFolded.GetValueOrDefault(EditorPrefs.GetBool($"com.lachee.utilities.UnityEventsFoldout", true)); 60 | set 61 | { 62 | _isFolded = value; 63 | EditorPrefs.SetBool($"com.lachee.utilities.UnityEventsFoldout", value); 64 | } 65 | } 66 | 67 | private float CalculateBackgroundHeight(SerializedProperty property) 68 | { 69 | var list = reorderableList; 70 | if (list == null || list.count == 0 || isFolded) 71 | return EditorGUIUtility.singleLineHeight + 2f; 72 | 73 | return base.GetPropertyHeight(property, GUIContent.none); 74 | } 75 | 76 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 77 | { 78 | RestoreState(property); 79 | 80 | text = label.text; 81 | dummyEvent = GetDummyEvent(property); 82 | 83 | float lineHeight = EditorGUIUtility.singleLineHeight; 84 | 85 | // Draw the folder 86 | if (reorderableList.count > 0) 87 | { 88 | isFolded = !EditorGUI.Foldout(new Rect(position.x, position.y, position.width, lineHeight), !isFolded, GUIContent.none); 89 | } 90 | else 91 | { 92 | _isFolded = true; 93 | } 94 | 95 | // Draw the event box 96 | Rect headerRect = new Rect(position.x + 2, position.y, position.width - 2, CalculateBackgroundHeight(property)); 97 | Rect headerLabel = new Rect(headerRect.x + 6, headerRect.y + 1, headerRect.width - 100, lineHeight); 98 | Rect headerAddButton = new Rect(headerRect.x + headerRect.width - 25, headerRect.y + 2, 24, headerRect.height + 4); 99 | 100 | // Draw the base GUI if we are unfolded 101 | if (!isFolded) 102 | { 103 | base.OnGUI(headerRect, property, label); 104 | } 105 | else 106 | { 107 | if (Event.current.type == EventType.Repaint) 108 | { 109 | GUI.backgroundColor = headerColor; 110 | headerBackground.Draw(headerRect, GUIContent.none, false, false, false, false); 111 | GUI.backgroundColor = Color.white; 112 | } 113 | 114 | DrawEventHeader(headerLabel); 115 | if (GUI.Button(headerAddButton, iconToolbarPlus, preButton)) 116 | { 117 | isFolded = false; 118 | OnAddEvent(reorderableList); 119 | } 120 | } 121 | } 122 | 123 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 124 | { 125 | return CalculateBackgroundHeight(property) + 5f; 126 | } 127 | 128 | } 129 | } 130 | #endif -------------------------------------------------------------------------------- /Runtime/Utilities/GLUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Utilities 6 | { 7 | /// 8 | /// Collection of tools to draw GL lines directly in the scene view 9 | /// 10 | public static class GLUtils 11 | { 12 | private static Material _lineMaterial; 13 | private static Material GetLineMaterial() 14 | { 15 | if (_lineMaterial != null) 16 | return _lineMaterial; 17 | 18 | // From: https://github.com/UnityCommunity/UnityLibrary/blob/master/Assets/Scripts/Helpers/DrawGLLine.cs 19 | 20 | // Unity has a built-in shader that is useful for drawing simple colored things 21 | var shader = Shader.Find("Hidden/Internal-Colored"); 22 | _lineMaterial = new Material(shader); 23 | _lineMaterial.hideFlags = HideFlags.HideAndDontSave; 24 | // Turn on alpha blending 25 | _lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); 26 | _lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); 27 | // Turn backface culling off 28 | _lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off); 29 | // Turn off depth writes 30 | _lineMaterial.SetInt("_ZWrite", 0); 31 | return _lineMaterial; 32 | } 33 | 34 | public static Transform transform; 35 | 36 | public static void DrawLines(Color color, params Vector3[] points) 37 | => DrawLines(GetLineMaterial(), color, points); 38 | public static void DrawLines(Material material, Color color, params Vector3[] points) 39 | { 40 | material.SetPass(0); 41 | GL.PushMatrix(); 42 | { 43 | if (transform) 44 | GL.MultMatrix(transform.localToWorldMatrix); 45 | 46 | GL.Begin(GL.LINE_STRIP); 47 | { 48 | GL.Color(color); 49 | for (int i = 0; i < points.Length; i++) 50 | GL.Vertex(points[i]); 51 | } 52 | GL.End(); 53 | } 54 | GL.PopMatrix(); 55 | } 56 | 57 | /// Draws a box on the XY axis 58 | public static void DrawBox(Color color, Vector3 center, Vector2 size) 59 | => DrawBox(GetLineMaterial(), color, center, size); 60 | /// Draws a box on the XY axis 61 | public static void DrawBox(Material material, Color color, Vector3 center, Vector2 size) 62 | { 63 | var hs = size / 2f; 64 | var tl = new Vector3(center.x - hs.x, center.y + hs.y); 65 | var tr = new Vector3(center.x + hs.x, center.y + hs.y); 66 | var bl = new Vector3(center.x - hs.x, center.y - hs.y); 67 | var br = new Vector3(center.x + hs.x, center.y - hs.y); 68 | 69 | // We are doing this, but we unfirl the loop for speed 70 | //DrawLines(material, color, tl, tr, br, bl, tl); 71 | material.SetPass(0); 72 | GL.PushMatrix(); 73 | { 74 | if (transform) 75 | GL.MultMatrix(transform.localToWorldMatrix); 76 | 77 | GL.Begin(GL.LINE_STRIP); 78 | { 79 | GL.Color(color); 80 | GL.Vertex(tl); 81 | GL.Vertex(tr); 82 | GL.Vertex(br); 83 | GL.Vertex(bl); 84 | GL.Vertex(tl); 85 | } 86 | GL.End(); 87 | } 88 | GL.PopMatrix(); 89 | } 90 | 91 | 92 | /// Draws a circle on the XY axis 93 | public static void DrawCircle(Color color, Vector3 center, float radius, int points = 16) 94 | => DrawCircle(GetLineMaterial(), color, center, radius, points); 95 | 96 | /// Draws a circle on the XY Axis 97 | public static void DrawCircle(Material material, Color color, Vector3 center, float radius, int points) { 98 | 99 | material.SetPass(0); 100 | GL.PushMatrix(); 101 | { 102 | if (transform) 103 | GL.MultMatrix(transform.localToWorldMatrix); 104 | 105 | GL.Begin(GL.LINE_STRIP); 106 | { 107 | GL.Color(color); 108 | for(int i = 0; i < points + 1; i++) 109 | { 110 | float progression = i / (float)points; 111 | float radians = progression * 2 * Mathf.PI; 112 | float x = center.x + radius * Mathf.Cos(radians); 113 | float y = center.y + radius * Mathf.Sin(radians); 114 | GL.Vertex(new Vector3(x, y, center.z)); 115 | } 116 | } 117 | GL.End(); 118 | } 119 | GL.PopMatrix(); 120 | } 121 | 122 | public static void DrawTest(Transform root, Color color) 123 | => DrawTest(root, GetLineMaterial(), color); 124 | public static void DrawTest(Transform root, Material material, Color color) 125 | { 126 | material.SetPass(0); 127 | 128 | GL.PushMatrix(); 129 | GL.MultMatrix(root.localToWorldMatrix); 130 | 131 | GL.Begin(GL.LINES); 132 | GL.Color(color); 133 | 134 | // start line from transform position 135 | GL.Vertex(root.position); 136 | // end line 100 units forward from transform position 137 | GL.Vertex(root.position + root.forward * 100); 138 | 139 | GL.End(); 140 | GL.PopMatrix(); 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /Runtime/Utilities/Extensions.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Lachee.Utilities 4 | { 5 | /// 6 | /// Extends GameObject functionality with a collection of utlities 7 | /// 8 | public static class GameObjectExtension 9 | { 10 | /// 11 | /// Sets the layer of the game object and its children 12 | /// 13 | /// The game object 14 | /// The new layer 15 | /// Ignores the object if it doesn't match the mask 16 | /// Stops recursion if the object doesn't match the mask 17 | public static void SetLayerRecursive(this GameObject obj, int layer, LayerMask mask = default(LayerMask), bool exitEarly = false) 18 | { 19 | if (!obj.SetLayer(layer, mask) && exitEarly) 20 | return; 21 | 22 | foreach(Transform child in obj.transform) 23 | child.gameObject.SetLayerRecursive(layer, mask); 24 | } 25 | 26 | /// 27 | /// Sets the layer of the game object 28 | /// 29 | /// The game object 30 | /// The new layer 31 | /// Ignores the object if it doesn't match the mask 32 | /// True if it matches and was updated 33 | public static bool SetLayer(this GameObject obj, int layer, LayerMask mask = default(LayerMask)) 34 | { 35 | if (mask == (mask | (1 << obj.layer))) 36 | { 37 | obj.layer = layer; 38 | return true; 39 | } 40 | return false; 41 | } 42 | } 43 | 44 | /// 45 | /// Extends RectRectangle 46 | /// 47 | public static class RectTransformExtension 48 | { 49 | /// Converts this rect transform to screen space 50 | public static Rect ToScreenSpace(this RectTransform transform) 51 | { 52 | Vector2 size = Vector2.Scale(transform.rect.size, transform.lossyScale); 53 | return new Rect((Vector2)transform.position - (size * 0.5f), size); 54 | } 55 | 56 | public static RectTransform SetLeft(this RectTransform rt, float left) 57 | { 58 | rt.offsetMin = new Vector2(left, rt.offsetMin.y); 59 | return rt; 60 | } 61 | 62 | public static RectTransform SetRight(this RectTransform rt, float right) 63 | { 64 | rt.offsetMax = new Vector2(-right, rt.offsetMax.y); 65 | return rt; 66 | } 67 | 68 | public static RectTransform SetTop(this RectTransform rt, float top) 69 | { 70 | rt.offsetMax = new Vector2(rt.offsetMax.x, -top); 71 | return rt; 72 | } 73 | 74 | public static RectTransform SetBottom(this RectTransform rt, float bottom) 75 | { 76 | rt.offsetMin = new Vector2(rt.offsetMin.x, bottom); 77 | return rt; 78 | } 79 | } 80 | 81 | /// 82 | /// Extends Transform 83 | /// 84 | public static class TransformExtension 85 | { 86 | /// 87 | /// Rotates around a pivot with the given rotation 88 | /// 89 | /// 90 | /// 91 | /// 92 | public static void RotateAround (this Transform transform, Vector3 pivotPoint, Quaternion rotation) 93 | { 94 | transform.position = rotation * (transform.position - pivotPoint) + pivotPoint; 95 | transform.rotation = rotation * transform.rotation; 96 | } 97 | } 98 | 99 | /// 100 | /// Extends Particle Systems 101 | /// 102 | public static class ParticleSystemExtension 103 | { 104 | /// Sets the max number of particles 105 | public static void SetMaxParticles(this ParticleSystem system, int count) 106 | { 107 | // Structs are referenced!? 108 | var module = system.main; 109 | module.maxParticles = count; 110 | } 111 | } 112 | 113 | /// 114 | /// Extends Color 115 | /// 116 | public static class ColorExtension 117 | { 118 | /// Converts the colour into a RGBA hex with the given prefix 119 | public static string ToHex(this Color color, char prefix = '#') 120 | { 121 | return prefix + ColorUtility.ToHtmlStringRGBA(color); 122 | } 123 | 124 | public static int PerceivedBrightness(this Color c) 125 | => ((Color32)c).PerceivedBrightness(); 126 | 127 | public static int PerceivedBrightness(this Color32 c) 128 | { 129 | // Rec 601 https://en.wikipedia.org/wiki/Rec._601 130 | return (int)Mathf.Sqrt( 131 | c.r * c.r * .299f + 132 | c.g * c.g * .587f + 133 | c.b * c.b * .114f); 134 | } 135 | } 136 | 137 | /// 138 | /// Extends sprites 139 | /// 140 | public static class SpriteExtensions 141 | { 142 | /// 143 | /// Gets the pixel data of the specific sprite. 144 | /// This will get the pixels from the base texture that only applies to this specific sprite. 145 | /// If the sprite texture is not set to read-write it will throw. 146 | /// If the sprite is part of a tightly packed alias it will throw. 147 | /// 148 | /// 149 | /// 150 | public static Color[] GetPixels(this Sprite sprite) 151 | { 152 | var texture = sprite.texture; 153 | var rect = sprite.textureRect; 154 | return texture.GetPixels( 155 | Mathf.RoundToInt(rect.x), 156 | Mathf.RoundToInt(rect.y), 157 | Mathf.RoundToInt(rect.width), 158 | Mathf.RoundToInt(rect.height) 159 | ); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Editor/Attributes/EnumFlagDrawer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace Lachee.Attributes.Editor 7 | { 8 | //src: http://wiki.unity3d.com/index.php/EnumFlagPropertyDrawer 9 | 10 | [CustomPropertyDrawer(typeof(EnumFlagAttribute))] 11 | public class EnumFlagDrawer : PropertyDrawer 12 | { 13 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 14 | { 15 | EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; 16 | if (flagSettings.isReadonly) 17 | GUI.color = new Color(0.65f, 0.65f, 0.65f); 18 | 19 | if (flagSettings.buttonMode) 20 | DrawButtons(position, property, label); 21 | else 22 | DrawMask(position, property, label); 23 | 24 | 25 | GUI.color = Color.white; 26 | } 27 | 28 | public void DrawButtons(Rect position, SerializedProperty property, GUIContent label) 29 | { 30 | EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; 31 | Enum targetEnum = GetBaseProperty(property); 32 | 33 | string propName = flagSettings.displayName; 34 | if (string.IsNullOrEmpty(propName)) propName = label.text; 35 | 36 | EditorGUI.LabelField(new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height), label); 37 | EditorGUI.BeginProperty(position, label, property); 38 | 39 | var values = Enum.GetValues(targetEnum.GetType()); 40 | string[] names = Enum.GetNames(targetEnum.GetType()); 41 | 42 | float buttonWidth = (position.width - EditorGUIUtility.labelWidth) / names.Length; 43 | 44 | int propValue = property.intValue; 45 | int buttonValue = 0; 46 | 47 | int index = 0; 48 | 49 | foreach (int value in values) 50 | { 51 | //Calculate the position of the button 52 | Rect buttonPos = new Rect(position.x + EditorGUIUtility.labelWidth + buttonWidth * index, position.y, buttonWidth, position.height); 53 | 54 | //Calculate the correct styling 55 | GUIStyle style = EditorStyles.miniButtonMid; 56 | if (index == 0) style = EditorStyles.miniButtonLeft; 57 | if (index == values.Length - 1) style = EditorStyles.miniButtonRight; 58 | if (values.Length == 1) style = EditorStyles.miniButton; 59 | 60 | //The value isn't 0, so we are not the first element 61 | if (value != 0) 62 | { 63 | if (GUI.Toggle(buttonPos, ((propValue & value) != 0), property.enumNames[index], style)) 64 | buttonValue |= value; 65 | } 66 | else 67 | { 68 | //The value is 0, so this is a nothing element. 69 | if (GUI.Toggle(buttonPos, propValue == value, property.enumNames[index], style)) 70 | { 71 | buttonValue = 0; 72 | propValue = 0; 73 | } 74 | } 75 | 76 | index++; 77 | } 78 | 79 | if (!flagSettings.isReadonly) 80 | property.intValue = buttonValue; 81 | 82 | EditorGUI.EndProperty(); 83 | } 84 | 85 | public void DrawMask(Rect position, SerializedProperty property, GUIContent label) 86 | { 87 | EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; 88 | Enum targetEnum = GetBaseProperty(property); 89 | 90 | string propName = flagSettings.displayName; 91 | if (string.IsNullOrEmpty(propName)) propName = property.name; 92 | 93 | EditorGUI.BeginProperty(position, label, property); 94 | 95 | Enum enumNew = EditorGUI.EnumFlagsField(position, propName, targetEnum); 96 | 97 | if (!flagSettings.isReadonly) 98 | property.intValue = (int)Convert.ChangeType(enumNew, targetEnum.GetType()); 99 | 100 | 101 | EditorGUI.EndProperty(); 102 | } 103 | 104 | public void DrawShitButtons(Rect position, SerializedProperty property, GUIContent label) 105 | { 106 | EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute; 107 | 108 | int buttonsIntValue = 0; 109 | int enumLength = property.enumNames.Length; 110 | bool[] buttonPressed = new bool[enumLength]; 111 | float buttonWidth = (position.width - EditorGUIUtility.labelWidth) / enumLength; 112 | 113 | int propertyValue = property.intValue; 114 | 115 | label.text += " " + propertyValue; 116 | EditorGUI.LabelField(new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height), label); 117 | 118 | EditorGUI.BeginChangeCheck(); 119 | 120 | if (flagSettings.isReadonly) 121 | GUI.color = new Color(0.65f, 0.65f, 0.65f); 122 | 123 | for (int i = 0; i < enumLength; i++) 124 | { 125 | 126 | // Check if the button is/was pressed 127 | if ((property.intValue & (1 << i)) == 1 << i) 128 | { 129 | buttonPressed[i] = true; 130 | } 131 | 132 | 133 | Rect buttonPos = new Rect(position.x + EditorGUIUtility.labelWidth + buttonWidth * i, position.y, buttonWidth, position.height); 134 | 135 | buttonPressed[i] = GUI.Toggle(buttonPos, buttonPressed[i], property.enumNames[i], "Button"); 136 | 137 | if (buttonPressed[i]) 138 | buttonsIntValue += 1 << i; 139 | } 140 | 141 | if (EditorGUI.EndChangeCheck() && !flagSettings.isReadonly) 142 | { 143 | property.intValue = buttonsIntValue; 144 | } 145 | 146 | GUI.color = Color.white; 147 | } 148 | 149 | static T GetBaseProperty(SerializedProperty prop) 150 | { 151 | // Separate the steps it takes to get to this property 152 | string[] separatedPaths = prop.propertyPath.Split('.'); 153 | 154 | // Go down to the root of this serialized property 155 | System.Object reflectionTarget = prop.serializedObject.targetObject as object; 156 | // Walk down the path to get the target object 157 | foreach (var path in separatedPaths) 158 | { 159 | FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField); 160 | reflectionTarget = fieldInfo.GetValue(reflectionTarget); 161 | } 162 | return (T)reflectionTarget; 163 | } 164 | } 165 | } -------------------------------------------------------------------------------- /Runtime/UYAML/Writer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace Lachee.UYAML 5 | { 6 | public class Writer 7 | { 8 | private const string DEFAULT_EOL = "\r\n"; 9 | private StringBuilder builder = new StringBuilder(); 10 | 11 | private string eol = DEFAULT_EOL; 12 | 13 | public int IndentationSpaces { get; set; } = 2; 14 | public bool InlineObjects { get; set; } = true; 15 | public bool InlineComplexObjects { get; set; } = false; 16 | public bool InlineArrays { get; set; } = true; 17 | public bool InlineComplexArrays { get; set; } = false; 18 | public int MaxInlineValues = 3; 19 | 20 | public bool IncludeHeader { get; set; } = true; 21 | 22 | public void AddComponets(IEnumerable components) 23 | { 24 | foreach (var component in components) 25 | AddComponent(component); 26 | } 27 | public void AddComponent(UComponent component) 28 | { 29 | builder.Append(Parser.COMPONENT_HEADER) 30 | .Append((int)component.classID) 31 | .Append(" &") 32 | .Append(component.fileID) 33 | .Append(eol); 34 | 35 | AppendProperty(component.rootProperty, 0, false, false); 36 | } 37 | 38 | private void AppendProperty(UProperty property, int indent, bool arrayItem, bool skipIndent) 39 | { 40 | int indentLevel = indent; 41 | int indentSize = IndentationSpaces; 42 | string name = string.IsNullOrEmpty(property.name) ? "" : property.name + ":"; 43 | 44 | if (arrayItem) 45 | { 46 | name = "-"; 47 | indentLevel -= 1; 48 | } 49 | 50 | if (skipIndent) 51 | indentSize = 0; 52 | 53 | switch (property.value) 54 | { 55 | default: break; 56 | case UValue uValue: 57 | builder.Append(' ', indentLevel * indentSize).Append(name).Append(" ").Append(uValue.value); 58 | builder.Append(eol); 59 | break; 60 | case UArray uArray: 61 | if (CanInline(uArray)) 62 | { 63 | builder.Append(' ', indentLevel * indentSize).Append(name).Append(" ["); 64 | eol = ""; 65 | bool first = true; 66 | for (int i = 0; i < uArray.items.Count; i++) 67 | { 68 | if (!first) builder.Append(","); 69 | AppendProperty(new UProperty(string.Empty, uArray.items[i]), 0, false, true); 70 | first = false; 71 | } 72 | 73 | eol = DEFAULT_EOL; 74 | builder.Append(']').Append(eol); 75 | } 76 | else 77 | { 78 | builder.Append(' ', indentLevel * indentSize).Append(name); 79 | builder.Append(eol); 80 | for (int i = 0; i < uArray.items.Count; i++) 81 | AppendProperty(new UProperty(string.Empty, uArray.items[i]), indentLevel + 1, true, false); 82 | } 83 | break; 84 | case UObject uObject: 85 | if (CanInline(uObject) ) 86 | { 87 | builder.Append(' ', indentLevel * indentSize).Append(name).Append(" {"); 88 | eol = ""; 89 | bool first = true; 90 | foreach (var kp in uObject.properties) 91 | { 92 | if (!first) builder.Append(", "); 93 | AppendProperty(kp.Value, 0, false, true); 94 | first = false; 95 | } 96 | eol = DEFAULT_EOL; 97 | builder.Append('}').Append(eol); 98 | } 99 | else 100 | { 101 | bool first = true; 102 | builder.Append(' ', indentLevel * indentSize).Append(name); 103 | builder.Append(arrayItem ? " " : eol); // This inlines the first time of an array 104 | foreach (var kp in uObject.properties) 105 | { 106 | AppendProperty(kp.Value, indentLevel + 1, false, arrayItem && first); 107 | first = false; 108 | } 109 | } 110 | break; 111 | } 112 | } 113 | 114 | private bool CanInline(UObject obj) 115 | { 116 | if (!InlineObjects) 117 | return false; 118 | 119 | if (obj.properties.Count == 0) 120 | return true; 121 | 122 | if (obj.properties.Count > MaxInlineValues) 123 | return false; 124 | 125 | foreach (var kp in obj.properties) 126 | { 127 | if (InlineComplexObjects) 128 | { 129 | if (kp.Value.value is UObject o && !CanInline(o)) 130 | return false; 131 | if (kp.Value.value is UArray a && !CanInline(a)) 132 | return false; 133 | } 134 | else 135 | { 136 | if (!(kp.Value.value is UValue)) 137 | return false; 138 | } 139 | } 140 | 141 | return true; 142 | } 143 | 144 | private bool CanInline(UArray arr) 145 | { 146 | if (!InlineArrays) 147 | return false; 148 | 149 | if (arr.items.Count == 0) 150 | return true; 151 | 152 | if (arr.items.Count > MaxInlineValues) 153 | return false; 154 | 155 | foreach (var item in arr.items) 156 | { 157 | if (InlineComplexArrays) 158 | { 159 | if (item is UObject o && !CanInline(o)) 160 | return false; 161 | if (item is UArray a && !CanInline(a)) 162 | return false; 163 | } 164 | else 165 | { 166 | if (!(item is UValue)) 167 | return false; 168 | } 169 | } 170 | return true; 171 | } 172 | 173 | /// 174 | /// Builds a UYAML document with the default settings 175 | /// 176 | /// 177 | /// 178 | public static string Build(IEnumerable components) 179 | { 180 | Writer writer = new Writer(); 181 | writer.AddComponets(components); 182 | return writer.ToString(); 183 | } 184 | 185 | public override string ToString() 186 | { 187 | string result = builder.ToString(); 188 | if (IncludeHeader) 189 | return $"%YAML 1.1{DEFAULT_EOL}%TAG !u! tag:unity3d.com,2011:{DEFAULT_EOL}" + result; 190 | return result; 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Runtime/Utilities/RandomList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Utilities 6 | { 7 | public interface IRandomList 8 | where K : System.IComparable 9 | { 10 | public int Count { get; } 11 | public K TotalWeight { get; } 12 | 13 | bool Randomise(float random, out T result); 14 | 15 | void Add(T item, K weight); 16 | void Remove(T item); 17 | void Clear(); 18 | 19 | K GetWeight(T item); 20 | bool TryGetWeight(T item, out K weight); 21 | bool SetWeight(T item, K weight); 22 | } 23 | 24 | /// 25 | /// A randomised list. It will store a collection of values with specified weights and provide functionallity to select randomly from the list. 26 | /// 27 | /// Type to store as the value. 28 | [System.Serializable] 29 | public class RandomList : IEnumerable, IRandomList 30 | { 31 | [SerializeField] private List _list; 32 | [SerializeField] private List _weights; 33 | [SerializeField] private float _sumWeight = 0; 34 | 35 | /// 36 | /// Number of elements currently in the table. 37 | /// 38 | public int Count { get { return _list.Count; } } 39 | 40 | /// 41 | /// The total tally of the weights. 42 | /// 43 | public float TotalWeight { get { return _sumWeight; } } 44 | 45 | /// 46 | /// Creates a new Random List 47 | /// 48 | public RandomList() 49 | { 50 | _list = new List(); 51 | _weights = new List(); 52 | } 53 | 54 | /// 55 | /// Creates a new Random List with a set capacity. 56 | /// 57 | /// 58 | public RandomList(int capacity) 59 | { 60 | _list = new List(capacity); 61 | _weights = new List(capacity); 62 | } 63 | 64 | public RandomList(IEnumerable> collection) : this() 65 | { 66 | foreach (var kp in collection) 67 | Add(kp); 68 | } 69 | 70 | /// 71 | /// Clears the random table. 72 | /// 73 | public void Clear() 74 | { 75 | _list.Clear(); 76 | _weights.Clear(); 77 | _sumWeight = 0; 78 | } 79 | 80 | /// 81 | /// Adds a new item with a specified weight to the table and increments the total weight. 82 | /// 83 | /// Item to add 84 | /// Non-negative weight this item has 85 | public void Add(T item, float weight = 1.0f) 86 | { 87 | if (weight < 0) 88 | { 89 | Debug.LogWarning("Weight for item " + item.ToString() + " is negative"); 90 | weight = 0; 91 | } 92 | 93 | _list.Add(item); 94 | _weights.Add(weight); 95 | _sumWeight += weight; 96 | } 97 | 98 | /// Adds a new key value pair 99 | public void Add(KeyValuePair pair) 100 | { 101 | Add(pair.Key, pair.Value); 102 | } 103 | 104 | /// Adds a random list to this one 105 | public void Add(RandomList other) 106 | { 107 | _list.AddRange(other._list); 108 | _weights.AddRange(other._weights); 109 | _sumWeight += other._sumWeight; 110 | } 111 | 112 | /// 113 | /// Removes an item and its weight 114 | /// 115 | /// The item to remove 116 | public void Remove(T item) 117 | { 118 | Debug.Assert(_list.Count == _weights.Count); 119 | 120 | var index = _list.IndexOf(item); 121 | if (index >= 0) 122 | { 123 | _list.RemoveAt(index); 124 | _sumWeight -= _weights[index]; 125 | _weights.RemoveAt(index); 126 | } 127 | } 128 | 129 | /// 130 | /// Updates the weight of a specific item 131 | /// 132 | /// The item to update 133 | /// Weight of the item 134 | /// If the item exists and was updated 135 | public bool SetWeight(T item, float weight) 136 | { 137 | Debug.Assert(_list.Count == _weights.Count); 138 | 139 | var index = _list.IndexOf(item); 140 | if (index < 0) return false; 141 | 142 | _sumWeight -= _weights[index]; 143 | _sumWeight += weight; 144 | _weights[index] = weight; 145 | return true; 146 | } 147 | 148 | /// 149 | /// Gets the weight of a specific item 150 | /// 151 | /// 152 | /// 153 | public float GetWeight(T item) 154 | { 155 | var index = _list.IndexOf(item); 156 | if (index < 0) 157 | throw new System.ArgumentOutOfRangeException("item", "The item does not exist within the collection"); 158 | return _weights[index]; 159 | } 160 | 161 | /// 162 | /// Tries to get the weight of a specific item 163 | /// 164 | /// 165 | /// 166 | /// 167 | public bool TryGetWeight(T item, out float weight) 168 | { 169 | weight = 0; 170 | var index = _list.IndexOf(item); 171 | if (index < 0) return false; 172 | weight = _weights[index]; 173 | return true; 174 | } 175 | 176 | /// 177 | /// Attempts to pick a random element from the table based of weighting. 178 | /// 179 | /// A random value between 0 and 1. This is done so System.Random or Unity.Random can be used. 180 | /// The random element that was fetched. 181 | /// false if we are unable to find a random element. 182 | public bool Randomise(float random, out T result) 183 | { 184 | Debug.Assert(_list.Count == _weights.Count); 185 | 186 | float rand = random * TotalWeight; 187 | for (int i = 0; i < _list.Count; i++) 188 | { 189 | rand -= _weights[i]; 190 | if (rand < 0) 191 | { 192 | result = _list[i]; 193 | return true; 194 | } 195 | } 196 | 197 | result = default(T); 198 | return false; 199 | } 200 | 201 | /// 202 | /// Recalculates the total weights 203 | /// 204 | protected float RecalculateWeights() 205 | { 206 | Debug.Assert(_list.Count == _weights.Count); 207 | 208 | _sumWeight = 0; 209 | for (int i = 0; i < _list.Count; i++) 210 | _sumWeight += _weights[i]; 211 | 212 | return _sumWeight; 213 | } 214 | 215 | /// 216 | /// Gets a enumerator of items in the Rist. Does not apply the random function too it. 217 | /// 218 | /// 219 | public IEnumerator GetEnumerator() 220 | { 221 | return _list.GetEnumerator(); 222 | } 223 | 224 | /// 225 | /// Gets a enumerator of items in the Rist. Does not apply the random function too it. 226 | /// 227 | /// 228 | IEnumerator IEnumerable.GetEnumerator() 229 | { 230 | return _list.GetEnumerator(); 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /Runtime/Utilities/RandomListInt.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Utilities 6 | { 7 | /// 8 | /// A randomised list. It will store a collection of values with specified weights and provide functionallity to select randomly from the list. 9 | /// 10 | /// Type to store as the value. 11 | [System.Serializable] 12 | public class RandomListInt : IEnumerable, IRandomList 13 | { 14 | [SerializeField] private List _list; 15 | [SerializeField] private List _weights; 16 | [SerializeField] private int _sumWeight = 0; 17 | 18 | /// 19 | /// Number of elements currently in the table. 20 | /// 21 | public int Count { get { return _list.Count; } } 22 | 23 | /// 24 | /// The total tally of the weights. 25 | /// 26 | public int TotalWeight { get { return _sumWeight; } } 27 | 28 | /// 29 | /// If false, then the weight will slowly decrement with every random, eventually landing on zero. 30 | /// 31 | public bool WithReplacement { get; set; } = true; 32 | 33 | /// 34 | /// Creates a new Random List 35 | /// 36 | public RandomListInt() 37 | { 38 | _list = new List(); 39 | _weights = new List(); 40 | } 41 | 42 | /// 43 | /// Creates a new Random List with a set capacity. 44 | /// 45 | /// 46 | public RandomListInt(int capacity) 47 | { 48 | _list = new List(capacity); 49 | _weights = new List(capacity); 50 | } 51 | 52 | public RandomListInt(RandomListInt other) : this(other.Count) 53 | { 54 | this.Add(other); 55 | } 56 | 57 | public RandomListInt(IEnumerable> collection) : this() 58 | { 59 | foreach (var kp in collection) 60 | Add(kp); 61 | } 62 | 63 | /// 64 | /// Clears the random table. 65 | /// 66 | public void Clear() 67 | { 68 | _list.Clear(); 69 | _weights.Clear(); 70 | _sumWeight = 0; 71 | } 72 | 73 | /// 74 | /// Adds a new item with a specified weight to the table and increments the total weight. 75 | /// 76 | /// Item to add 77 | /// Non-negative weight this item has 78 | public void Add(T item, int weight = 1) 79 | { 80 | if (weight < 0) 81 | { 82 | Debug.LogWarning("Weight for item " + item.ToString() + " is negative"); 83 | weight = 0; 84 | } 85 | 86 | _list.Add(item); 87 | _weights.Add(weight); 88 | _sumWeight += weight; 89 | } 90 | 91 | /// Adds a new key value pair 92 | public void Add(KeyValuePair pair) 93 | { 94 | Add(pair.Key, pair.Value); 95 | } 96 | 97 | /// Adds a random list to this one 98 | public void Add(RandomListInt other) 99 | { 100 | _list.AddRange(other._list); 101 | _weights.AddRange(other._weights); 102 | _sumWeight += other._sumWeight; 103 | } 104 | 105 | /// 106 | /// Removes an item and its weight 107 | /// 108 | /// The item to remove 109 | public void Remove(T item) 110 | { 111 | Debug.Assert(_list.Count == _weights.Count); 112 | 113 | var index = _list.IndexOf(item); 114 | if (index >= 0) 115 | { 116 | _list.RemoveAt(index); 117 | _sumWeight -= _weights[index]; 118 | _weights.RemoveAt(index); 119 | } 120 | } 121 | 122 | /// 123 | /// Updates the weight of a specific item 124 | /// 125 | /// The item to update 126 | /// Weight of the item 127 | /// If the item exists and was updated 128 | public bool SetWeight(T item, int weight) 129 | { 130 | Debug.Assert(_list.Count == _weights.Count); 131 | 132 | var index = _list.IndexOf(item); 133 | if (index < 0) return false; 134 | 135 | _sumWeight -= _weights[index]; 136 | _sumWeight += weight; 137 | _weights[index] = weight; 138 | return true; 139 | } 140 | 141 | /// 142 | /// Gets the weight of a specific item 143 | /// 144 | /// 145 | /// 146 | public int GetWeight(T item) 147 | { 148 | var index = _list.IndexOf(item); 149 | if (index < 0) 150 | throw new System.ArgumentOutOfRangeException("item", "The item does not exist within the collection"); 151 | return _weights[index]; 152 | } 153 | 154 | /// 155 | /// Tries to get the weight of a specific item 156 | /// 157 | /// 158 | /// 159 | /// 160 | public bool TryGetWeight(T item, out int weight) 161 | { 162 | weight = 0; 163 | var index = _list.IndexOf(item); 164 | if (index < 0) return false; 165 | weight = _weights[index]; 166 | return true; 167 | } 168 | 169 | /// 170 | /// Attempts to pick a random element from the table based of weighting. 171 | /// 172 | /// A random value between 0 and 1. This is done so System.Random or Unity.Random can be used. 173 | /// The random element that was fetched. 174 | /// false if we are unable to find a random element. 175 | public bool Randomise(float random, out T result) 176 | { 177 | Debug.Assert(_list.Count == _weights.Count); 178 | 179 | float rand = random * TotalWeight; 180 | for (int i = 0; i < _list.Count; i++) 181 | { 182 | rand -= _weights[i]; 183 | if (rand < 0) 184 | { 185 | result = _list[i]; 186 | if (!WithReplacement && _weights[i] > 0) 187 | { 188 | _weights[i] -= 1; 189 | _sumWeight -= 1; 190 | } 191 | 192 | return true; 193 | } 194 | } 195 | 196 | result = default(T); 197 | return false; 198 | } 199 | 200 | /// 201 | /// Recalculates the total weights 202 | /// 203 | protected int RecalculateWeights() 204 | { 205 | Debug.Assert(_list.Count == _weights.Count); 206 | 207 | _sumWeight = 0; 208 | for (int i = 0; i < _list.Count; i++) 209 | _sumWeight += _weights[i]; 210 | 211 | return _sumWeight; 212 | } 213 | 214 | 215 | /// 216 | /// Gets a enumerator of items in the Rist. Does not apply the random function too it. 217 | /// 218 | /// 219 | public IEnumerator GetEnumerator() 220 | { 221 | return _list.GetEnumerator(); 222 | } 223 | 224 | /// 225 | /// Gets a enumerator of items in the Rist. Does not apply the random function too it. 226 | /// 227 | /// 228 | IEnumerator IEnumerable.GetEnumerator() 229 | { 230 | return _list.GetEnumerator(); 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /Runtime/Utilities/SortedGizmos.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Lachee.Utilities 6 | { 7 | /// Lachee's Gizmos 8 | public static class Gizmol { 9 | 10 | public static void DrawExclamation(Vector3 position, float scale = 1f) 11 | { 12 | Gizmos.DrawCube(position, new Vector3(0.25f, 0.25f, 0.25f) * scale); 13 | Gizmos.DrawCube(position + Vector3.up * 0.75f * scale, new Vector3(0.25f, 1f, 0.25f) * scale); 14 | } 15 | 16 | /// Draws a Gizmos text at the given position 17 | public static void Label(Vector3 position, string text) { 18 | #if UNITY_EDITOR 19 | //Draw the node as a string 20 | UnityEditor.Handles.Label(position, text); 21 | #endif 22 | } 23 | 24 | public static void Label(Vector3 position, string format, params object[] objects) { 25 | Label(position, string.Format(format, objects)); 26 | } 27 | } 28 | 29 | #pragma warning disable 0649, CS0649 30 | public static class SortedGizmos 31 | { 32 | #if UNITY_EDITOR 33 | static List commands = new List(1000); 34 | #endif 35 | 36 | public static Color color { 37 | get 38 | { 39 | if (correctColor) 40 | { 41 | const float correction = 1.5f; 42 | return new Color(_color.r * correction, _color.g * correction, _color.b * correction, _color.a); 43 | } 44 | return _color; 45 | } 46 | set { _color = value; } 47 | } 48 | private static Color _color; 49 | public static bool correctColor = false; 50 | 51 | public static void BatchCommit() 52 | { 53 | #if UNITY_EDITOR 54 | Camera cam = null; 55 | var sv = UnityEditor.SceneView.currentDrawingSceneView; 56 | if (sv != null && sv.camera != null) 57 | { 58 | cam = sv.camera; 59 | } 60 | else 61 | { 62 | cam = Camera.main; 63 | } 64 | if (cam != null) 65 | { 66 | var mat = cam.worldToCameraMatrix; 67 | for (int i = 0; i < commands.Count; ++i) 68 | { 69 | commands[i].Transform(mat); 70 | } 71 | // sort by z 72 | var a = commands.ToArray(); 73 | Array.Sort(a, compareCommands); 74 | // draw 75 | for (int i = 0; i < a.Length; ++i) 76 | { 77 | a[i].Draw(); 78 | } 79 | } 80 | commands.Clear(); 81 | #endif 82 | } 83 | 84 | public static void DrawSphere(Vector3 center, float radius) 85 | { 86 | #if UNITY_EDITOR 87 | commands.Add(new DrawSolidSphereCommand 88 | { 89 | color = color, 90 | position = center, 91 | radius = radius 92 | }); 93 | #endif 94 | } 95 | 96 | public static void DrawWireSphere(Vector3 center, float radius) 97 | { 98 | #if UNITY_EDITOR 99 | commands.Add(new DrawWireSphereCommand 100 | { 101 | color = color, 102 | position = center, 103 | radius = radius 104 | }); 105 | #endif 106 | } 107 | 108 | public static void DrawCube(Vector3 center, Vector3 size) 109 | { 110 | #if UNITY_EDITOR 111 | commands.Add(new DrawSolidCubeCommand 112 | { 113 | color = color, 114 | position = center, 115 | size = size 116 | }); 117 | #endif 118 | } 119 | 120 | public static void DrawWireCube(Vector3 center, Vector3 size) 121 | { 122 | #if UNITY_EDITOR 123 | commands.Add(new DrawWireCubeCommand 124 | { 125 | color = color, 126 | position = center, 127 | size = size 128 | }); 129 | #endif 130 | } 131 | 132 | #if UNITY_EDITOR 133 | static int compareCommands(ICommand a, ICommand b) 134 | { 135 | float diff = a.SortValue - b.SortValue; 136 | if (diff < 0f) return -1; 137 | else if (diff > 0f) return 1; 138 | else return 0; 139 | } 140 | 141 | interface ICommand 142 | { 143 | void Transform(Matrix4x4 worldToCamera); 144 | void Draw(); 145 | float SortValue { get; } 146 | } 147 | 148 | struct DrawSolidSphereCommand : ICommand 149 | { 150 | public Color color; 151 | public Vector3 position; 152 | public float radius; 153 | 154 | private Vector3 transformedPosition; 155 | 156 | public void Transform(Matrix4x4 mat) 157 | { 158 | transformedPosition = mat.MultiplyPoint(position); 159 | } 160 | 161 | public void Draw() 162 | { 163 | Gizmos.color = color; 164 | Gizmos.DrawSphere(position, radius); 165 | } 166 | 167 | public float SortValue { get { return transformedPosition.z; } } 168 | } 169 | 170 | struct DrawWireSphereCommand : ICommand 171 | { 172 | public Color color; 173 | public Vector3 position; 174 | public float radius; 175 | 176 | private Vector3 transformedPosition; 177 | 178 | public void Transform(Matrix4x4 mat) 179 | { 180 | transformedPosition = mat.MultiplyPoint(position); 181 | } 182 | 183 | public void Draw() 184 | { 185 | Gizmos.color = color; 186 | Gizmos.DrawWireSphere(position, radius); 187 | } 188 | 189 | public float SortValue { get { return transformedPosition.z; } } 190 | } 191 | 192 | struct DrawSolidCubeCommand : ICommand 193 | { 194 | public Color color; 195 | public Vector3 position; 196 | public Vector3 size; 197 | 198 | private Vector3 transformedPosition; 199 | 200 | public void Transform(Matrix4x4 mat) 201 | { 202 | transformedPosition = mat.MultiplyPoint(position); 203 | } 204 | 205 | public void Draw() 206 | { 207 | Gizmos.color = color; 208 | Gizmos.DrawCube(position, size); 209 | } 210 | 211 | public float SortValue { get { return transformedPosition.z; } } 212 | } 213 | 214 | struct DrawWireCubeCommand : ICommand 215 | { 216 | public Color color; 217 | public Vector3 position; 218 | public Vector3 size; 219 | 220 | private Vector3 transformedPosition; 221 | 222 | public void Transform(Matrix4x4 mat) 223 | { 224 | transformedPosition = mat.MultiplyPoint(position); 225 | } 226 | 227 | public void Draw() 228 | { 229 | Gizmos.color = color; 230 | Gizmos.DrawWireCube(position, size); 231 | } 232 | 233 | public float SortValue { get { return transformedPosition.z; } } 234 | } 235 | 236 | struct DrawSolidMeshCommand : ICommand 237 | { 238 | public Color color; 239 | public Vector3 position; 240 | public Vector3 scale; 241 | public Quaternion rotation; 242 | public Mesh mesh; 243 | 244 | private Vector3 transformedPosition; 245 | 246 | public void Transform(Matrix4x4 mat) 247 | { 248 | transformedPosition = mat.MultiplyPoint(position); 249 | } 250 | 251 | public void Draw() 252 | { 253 | Gizmos.color = color; 254 | Gizmos.DrawMesh(mesh, position, rotation, scale); 255 | } 256 | 257 | public float SortValue { get { return transformedPosition.z; } } 258 | } 259 | 260 | struct DrawWireMeshCommand : ICommand 261 | { 262 | public Color color; 263 | public Vector3 position; 264 | public Vector3 scale; 265 | public Quaternion rotation; 266 | public Mesh mesh; 267 | 268 | private Vector3 transformedPosition; 269 | 270 | public void Transform(Matrix4x4 mat) 271 | { 272 | transformedPosition = mat.MultiplyPoint(position); 273 | } 274 | 275 | public void Draw() 276 | { 277 | Gizmos.color = color; 278 | Gizmos.DrawWireMesh(mesh, position, rotation, scale); 279 | } 280 | 281 | public float SortValue { get { return transformedPosition.z; } } 282 | } 283 | #endif 284 | } 285 | #pragma warning restore 0649, CS0649 286 | } -------------------------------------------------------------------------------- /Editor/Utilities/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Linq; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | namespace Lachee.Utilities.Editor 9 | { 10 | public static class SerializedPropertyExtensions 11 | { 12 | /// 13 | /// Gets the type of the underlying field the SerializedProperty is of. 14 | /// 15 | /// The property to get the type from 16 | /// 17 | public static System.Type GetSerializedType(this SerializedProperty property) 18 | { 19 | return property.GetSerializedFieldInfo()?.FieldType; 20 | } 21 | 22 | /// 23 | /// Gets the FieldInfo of the underlying field 24 | /// 25 | /// The property to get the FieldInfo off 26 | /// 27 | public static FieldInfo GetSerializedFieldInfo(this SerializedProperty property) 28 | { 29 | System.Type parentType = property.serializedObject.targetObject.GetType(); 30 | return parentType.GetFieldInfoFromPath(property.propertyPath); 31 | } 32 | 33 | /// 34 | /// Gets the underlying value this property represents 35 | /// 36 | /// 37 | /// 38 | public static object GetSerializedValue(this SerializedProperty property) 39 | { 40 | #if !DISABLE_FAST_SERIALIZED_VALUE_LOOKUP 41 | switch (property.propertyType) 42 | { 43 | default: // If we cant find anything, we should just use the raw .ToString of the value 44 | case SerializedPropertyType.Enum: // Its easier to just lookup the enum properties than recreating it 45 | break; 46 | 47 | // Manually get a bunch because its more efficient than looking up serialized values 48 | case SerializedPropertyType.ObjectReference: 49 | return property.objectReferenceValue ? property.objectReferenceValue : null; 50 | case SerializedPropertyType.Boolean: 51 | return property.boolValue; 52 | case SerializedPropertyType.Integer: 53 | return property.intValue; 54 | case SerializedPropertyType.Float: 55 | return property.floatValue; 56 | case SerializedPropertyType.String: 57 | return property.stringValue; 58 | case SerializedPropertyType.Color: 59 | return property.colorValue; 60 | case SerializedPropertyType.Vector2: 61 | return property.vector2Value; 62 | case SerializedPropertyType.Vector3: 63 | return property.vector3Value; 64 | case SerializedPropertyType.Vector4: 65 | return property.vector4Value; 66 | case SerializedPropertyType.Vector2Int: 67 | return property.vector2IntValue; 68 | case SerializedPropertyType.Vector3Int: 69 | return property.vector3IntValue; 70 | case SerializedPropertyType.Quaternion: 71 | return property.quaternionValue; 72 | case SerializedPropertyType.Bounds: 73 | return property.boundsValue; 74 | case SerializedPropertyType.BoundsInt: 75 | return property.boundsIntValue; 76 | case SerializedPropertyType.Rect: 77 | return property.rectValue; 78 | case SerializedPropertyType.RectInt: 79 | return property.rectIntValue; 80 | } 81 | #endif 82 | // Lookup the property path and pull teh value directly 83 | System.Type parentType = property.serializedObject.targetObject.GetType(); 84 | return parentType.GetValueFromPath(property.serializedObject.targetObject, property.propertyPath); 85 | } 86 | 87 | /// 88 | /// Finds the field info for the given type at the given path. 89 | /// 90 | /// 91 | /// 92 | /// 93 | /// Does not work with arrays yet as they would return a PropertyInfo instead 94 | /// 95 | public static FieldInfo GetFieldInfoFromPath(this System.Type type, string path, BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField) 96 | { 97 | System.Type parentType = type; 98 | FieldInfo fi = type.GetField(path, flag); 99 | if (fi != null) return fi; 100 | 101 | string[] perDot = path.Split('.'); 102 | foreach (string fieldName in perDot) 103 | { 104 | fi = parentType.GetField(fieldName, flag); 105 | if (fi != null) 106 | parentType = fi.FieldType; 107 | else 108 | return null; 109 | } 110 | if (fi != null) 111 | return fi; 112 | else return null; 113 | } 114 | 115 | /// 116 | /// Gets the field values from the given path 117 | /// 118 | /// The type of the root object 119 | /// The root object to get the value from 120 | /// The SerializedProperty formatted path 121 | /// The flag used to search fields. 122 | /// 123 | public static object GetValueFromPath(this System.Type type, object context, string path, BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField) 124 | { 125 | object result = context; 126 | System.Type resultType = type; 127 | 128 | // We need to delve deeper until we hit the final result. 129 | string[] segments = path.Split('.'); 130 | for (int i = 0; i < segments.Length; i++) 131 | { 132 | // If the field name is an array we need to break apart the next segment to extract its index. 133 | // Once we have the index we can then use the `this` property arrays have to get the appropriate item and 134 | // continue our search through the list of paths. 135 | string fieldName = segments[i]; 136 | if (fieldName == "Array") 137 | { 138 | // parse the index 139 | string arrIndexPath = segments[++i]; 140 | string arrIndexStr = arrIndexPath.Substring(5, arrIndexPath.Length - 1 - 5); 141 | int arrIndex = int.Parse(arrIndexStr); 142 | 143 | // get the property 144 | var thisProperty = resultType.GetProperty("Item", new System.Type[] { arrIndex.GetType() }); 145 | var thisGetter = thisProperty.GetMethod; 146 | 147 | // Update the current state 148 | result = thisGetter.Invoke(result, new object[] { arrIndex }); 149 | resultType = result.GetType(); 150 | } 151 | else 152 | { 153 | var fi = resultType.GetField(fieldName, flag); 154 | if (fi == null) return null; 155 | 156 | resultType = fi.FieldType; 157 | result = fi.GetValue(result); 158 | } 159 | } 160 | 161 | return result; 162 | } 163 | 164 | 165 | /// 166 | /// Determines the best name for the given property 167 | /// 168 | /// 169 | /// 170 | public static string GetReadableName(this SerializedProperty property) 171 | { 172 | switch (property.propertyType) 173 | { 174 | default: 175 | return property.displayName; 176 | case SerializedPropertyType.ObjectReference: 177 | return property.objectReferenceValue ? property.objectReferenceValue.name : "[ NULL ]"; 178 | } 179 | } 180 | 181 | /// 182 | /// Gets the value of the property as a string 183 | /// 184 | /// 185 | /// 186 | public static string GetValueName(this SerializedProperty property) 187 | { 188 | object value = property.GetSerializedValue(); 189 | if (value == null) return "[ NULL ]"; 190 | 191 | if (value is float vFloat) 192 | return vFloat.ToString("n3"); 193 | 194 | if (value is Color vColor) 195 | return vColor.ToHex(); 196 | 197 | return value.ToString(); 198 | } 199 | } 200 | } --------------------------------------------------------------------------------