├── .editorconfig ├── .github └── workflows │ ├── build.yaml │ └── test.yaml ├── .gitignore ├── CONTRIBUTING.md ├── DarkConfig.sln ├── Docs ├── DarkConfig.png ├── custom_parsing.md ├── docnode.md ├── hotloading.md ├── migrating_from_v1.md ├── sources.md ├── tests.md ├── types.md └── validation.md ├── LICENSE.txt ├── README.md ├── THANKS.md ├── demo ├── Assets │ ├── DarkConfig.meta │ ├── DarkConfig │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── EditorUtils.cs │ │ │ └── EditorUtils.cs.meta │ │ ├── ResourcesSource.cs │ │ ├── ResourcesSource.cs.meta │ │ ├── UnityPlatform.cs │ │ ├── UnityPlatform.cs.meta │ │ ├── UnityTypeReifiers.cs │ │ └── UnityTypeReifiers.cs.meta │ ├── Demo.meta │ ├── Demo │ │ ├── Art.meta │ │ ├── Art │ │ │ ├── Bullet.png │ │ │ ├── Bullet.png.meta │ │ │ ├── City_Repeat.jpg │ │ │ ├── City_Repeat.jpg.meta │ │ │ ├── Clouds_Repeat.png │ │ │ ├── Clouds_Repeat.png.meta │ │ │ ├── circle.png │ │ │ ├── circle.png.meta │ │ │ ├── fuselage.png │ │ │ ├── fuselage.png.meta │ │ │ ├── plane.svg │ │ │ ├── plane.svg.meta │ │ │ ├── plus.png │ │ │ ├── plus.png.meta │ │ │ ├── puff.png │ │ │ ├── puff.png.meta │ │ │ ├── stabilizer.png │ │ │ ├── stabilizer.png.meta │ │ │ ├── wing.png │ │ │ └── wing.png.meta │ │ ├── Material.meta │ │ ├── Material │ │ │ ├── City.mat │ │ │ ├── City.mat.meta │ │ │ ├── Clouds.mat │ │ │ ├── Clouds.mat.meta │ │ │ ├── Clouds2.mat │ │ │ ├── Clouds2.mat.meta │ │ │ ├── Puff.mat │ │ │ ├── Puff.mat.meta │ │ │ ├── ShotFireParticle.mat │ │ │ └── ShotFireParticle.mat.meta │ │ ├── Prefabs.meta │ │ ├── Prefabs │ │ │ ├── Bullet.prefab │ │ │ ├── Bullet.prefab.meta │ │ │ ├── BulletHitFX.prefab │ │ │ ├── BulletHitFX.prefab.meta │ │ │ ├── Enemy.prefab │ │ │ ├── Enemy.prefab.meta │ │ │ ├── Explosion.prefab │ │ │ ├── Explosion.prefab.meta │ │ │ ├── Pickup.prefab │ │ │ ├── Pickup.prefab.meta │ │ │ ├── PlaneView.prefab │ │ │ ├── PlaneView.prefab.meta │ │ │ ├── Player.prefab │ │ │ ├── Player.prefab.meta │ │ │ ├── ShotFireFX.prefab │ │ │ ├── ShotFireFX.prefab.meta │ │ │ ├── Title.prefab │ │ │ └── Title.prefab.meta │ │ ├── Resources.meta │ │ ├── Resources │ │ │ ├── Configs.meta │ │ │ └── Configs │ │ │ │ ├── Planes.meta │ │ │ │ ├── Planes │ │ │ │ ├── SmallPlanes.bytes │ │ │ │ ├── SmallPlanes.bytes.meta │ │ │ │ ├── Whip.bytes │ │ │ │ └── Whip.bytes.meta │ │ │ │ ├── enemy_spawning.bytes │ │ │ │ ├── enemy_spawning.bytes.meta │ │ │ │ ├── guns.bytes │ │ │ │ ├── guns.bytes.meta │ │ │ │ ├── index.bytes │ │ │ │ ├── index.bytes.meta │ │ │ │ ├── player.bytes │ │ │ │ └── player.bytes.meta │ │ ├── Scenes.meta │ │ ├── Scenes │ │ │ ├── Loader.unity │ │ │ ├── Loader.unity.meta │ │ │ ├── PlaneDemo.unity │ │ │ └── PlaneDemo.unity.meta │ │ ├── Scripts.meta │ │ ├── Scripts │ │ │ ├── AIController.cs │ │ │ ├── AIController.cs.meta │ │ │ ├── Bullet.cs │ │ │ ├── Bullet.cs.meta │ │ │ ├── CameraFollow.cs │ │ │ ├── CameraFollow.cs.meta │ │ │ ├── Editor.meta │ │ │ ├── Editor │ │ │ │ ├── DemoEditorMenus.cs │ │ │ │ └── DemoEditorMenus.cs.meta │ │ │ ├── EnemySpawner.cs │ │ │ ├── EnemySpawner.cs.meta │ │ │ ├── GunCard.cs │ │ │ ├── GunCard.cs.meta │ │ │ ├── LoadGame.cs │ │ │ ├── LoadGame.cs.meta │ │ │ ├── Location.cs │ │ │ ├── Location.cs.meta │ │ │ ├── MetaGame.cs │ │ │ ├── MetaGame.cs.meta │ │ │ ├── Parallax.cs │ │ │ ├── Parallax.cs.meta │ │ │ ├── Pickup.cs │ │ │ ├── Pickup.cs.meta │ │ │ ├── PlaneCard.cs │ │ │ ├── PlaneCard.cs.meta │ │ │ ├── PlaneController.cs │ │ │ ├── PlaneController.cs.meta │ │ │ ├── PlaneView.cs │ │ │ ├── PlaneView.cs.meta │ │ │ ├── PlayerController.cs │ │ │ └── PlayerController.cs.meta │ │ ├── generate_random_configs.py │ │ └── generate_random_configs.py.meta │ ├── Editor.meta │ ├── Editor │ │ ├── Tests.meta │ │ └── Tests │ │ │ ├── UnitySpecificTests.cs │ │ │ └── UnitySpecificTests.cs.meta │ └── Plugins.meta ├── Packages │ ├── manifest.json │ └── packages-lock.json └── ProjectSettings │ ├── AudioManager.asset │ ├── ClusterInputManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── MemorySettings.asset │ ├── NavMeshAreas.asset │ ├── NavMeshLayers.asset │ ├── NetworkManager.asset │ ├── PackageManagerSettings.asset │ ├── Physics2DSettings.asset │ ├── PresetManager.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── TagManager.asset │ ├── TimeManager.asset │ ├── UnityConnectSettings.asset │ ├── VFXManager.asset │ ├── VersionControlSettings.asset │ └── XRSettings.asset ├── src └── DarkConfig │ ├── Attributes.cs │ ├── ConfigFileInfo.cs │ ├── ConfigProcessor.cs │ ├── ConfigSource.cs │ ├── Configs.cs │ ├── DarkConfig.csproj │ ├── DocNode │ ├── ComposedDocNode.cs │ ├── DocNode.cs │ └── YamlDocNode.cs │ ├── Exceptions.cs │ ├── FileSource.cs │ ├── Internal │ ├── BuiltInTypeReifiers.cs │ ├── ChecksumUtils.cs │ ├── ConfigFileManager.cs │ ├── DocumentationGenerator.cs │ ├── MultiCaseDictionary.cs │ ├── ReflectionCache.cs │ ├── RegexUtils.cs │ ├── StringExtensions.cs │ └── TypeReifier.cs │ └── Settings.cs └── test ├── ConfigKeyTests.cs ├── DarkConfig.Tests.csproj ├── DictComposingTests.cs ├── DocNodeExtensionTests.cs ├── DocNodeMergeTests.cs ├── FileSourceTests.cs ├── FromDocTests.cs ├── GlobMatchTests.cs ├── ListComposingTests.cs ├── MissingFilesTests.cs ├── PostDocTests.cs ├── TypeReifierTests.cs └── YamlParseTests.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Baseline 7 | [*] 8 | charset = utf-8 9 | tab_width = 4 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.csproj] 14 | indent_style = tab 15 | indent_size = 4 16 | 17 | [*.cs] 18 | indent_style = space 19 | indent_size = 4 20 | max_line_length = 120 21 | 22 | # Microsoft .NET properties 23 | csharp_indent_braces = false 24 | csharp_new_line_before_catch = false 25 | csharp_new_line_before_else = false 26 | csharp_new_line_before_open_brace = none 27 | csharp_preferred_modifier_order = public, private, override, virtual, file, new, abstract, internal, protected, sealed, static, readonly, extern, unsafe, volatile, async, required:suggestion 28 | csharp_preserve_single_line_blocks = true 29 | csharp_space_after_cast = true 30 | csharp_style_var_for_built_in_types = false:suggestion 31 | dotnet_sort_system_directives_first = false 32 | dotnet_style_require_accessibility_modifiers = never:suggestion 33 | 34 | # ReSharper properties 35 | resharper_align_multiline_binary_expressions_chain = false 36 | resharper_allow_comment_after_lbrace = true 37 | resharper_blank_lines_after_block_statements = 0 38 | resharper_blank_lines_around_auto_property = 0 39 | resharper_blank_lines_around_local_method = 0 40 | resharper_blank_lines_around_property = 0 41 | resharper_blank_lines_around_single_line_type = 1 42 | resharper_braces_for_for = required 43 | resharper_braces_for_foreach = required 44 | resharper_braces_for_ifelse = not_required 45 | resharper_braces_for_while = required 46 | resharper_braces_redundant = false 47 | resharper_csharp_blank_lines_around_field = 0 48 | resharper_csharp_blank_lines_around_type = 0 49 | resharper_csharp_blank_lines_inside_region = 0 50 | resharper_csharp_empty_block_style = together 51 | resharper_csharp_insert_final_newline = true 52 | resharper_csharp_max_line_length = 172 53 | resharper_csharp_remove_blank_lines_near_braces_in_declarations = false 54 | resharper_csharp_wrap_before_binary_opsign = true 55 | resharper_csharp_wrap_ternary_expr_style = wrap_if_long 56 | resharper_default_value_when_type_evident = default_expression 57 | resharper_indent_pars = outside 58 | resharper_instance_members_qualify_declared_in = 59 | resharper_keep_existing_attribute_arrangement = true 60 | resharper_keep_existing_declaration_block_arrangement = false 61 | resharper_keep_existing_enum_arrangement = false 62 | resharper_max_attribute_length_for_same_line = 20 63 | resharper_csharp_object_creation_when_type_evident = target_typed 64 | resharper_csharp_object_creation_when_type_not_evident = target_typed 65 | resharper_parentheses_non_obvious_operations = none, bitwise_and, bitwise_exclusive_or, bitwise_inclusive_or, bitwise 66 | resharper_parentheses_redundancy_style = remove 67 | resharper_place_accessorholder_attribute_on_same_line = false 68 | resharper_place_expr_accessor_on_single_line = true 69 | resharper_place_expr_method_on_single_line = true 70 | resharper_place_simple_initializer_on_single_line = false 71 | resharper_space_within_single_line_array_initializer_braces = false 72 | resharper_wrap_array_initializer_style = chop_if_long 73 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | build: 9 | runs-on: windows-latest 10 | 11 | strategy: 12 | matrix: 13 | dotnet-version: ['8.0'] 14 | configuration: 15 | - Debug 16 | - Release 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} 22 | uses: actions/setup-dotnet@v2 23 | with: 24 | dotnet-version: ${{ matrix.dotnet-version }} 25 | 26 | - name: Build 27 | run: dotnet build --configuration ${{ matrix.configuration }} -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | test: 9 | runs-on: windows-latest 10 | 11 | strategy: 12 | matrix: 13 | dotnet-version: ['8.0'] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} 19 | uses: actions/setup-dotnet@v2 20 | with: 21 | dotnet-version: ${{ matrix.dotnet-version }} 22 | 23 | - name: Run Tests 24 | run: dotnet test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # intermediate directories 2 | obj 3 | bin 4 | test/bin 5 | test/obj 6 | packages/ 7 | 8 | # demo Unity files 9 | demo/Library 10 | demo/Temp 11 | demo/UserSettings 12 | demo/Logs 13 | demo/**/*.sln 14 | demo/**/*.csproj 15 | demo/**/*.unityproj 16 | demo/**/Builds 17 | demo/**/UnitTestResults.xml* 18 | demo/**/*-TestResults.xml* 19 | 20 | # these are copied here as a post-build step in the normal csproj 21 | demo/Assets/Plugins/DarkConfig.dll 22 | demo/Assets/Plugins/DarkConfig.dll.meta 23 | demo/Assets/Plugins/YamlDotNet.dll 24 | demo/Assets/Plugins/YamlDotNet.dll.meta 25 | 26 | .idea 27 | .vscode 28 | *.userprefs 29 | *.suo 30 | *.user 31 | *.pidb 32 | *.userprefs 33 | *.userprefs.meta -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | CONTRIBUTING 2 | ============== 3 | 4 | Thanks for thinking about contributing to DarkConfig! There's a lot of ways that someone can contribute to an open source project, many of which can be done without programming experience. For general information check out [this article](https://blog.newrelic.com/2014/05/05/open-source_gettingstarted/), or [this one](https://guides.github.com/activities/contributing-to-open-source/). 5 | 6 | - Help organize issues. Detect and consolidate duplicates. Reply to issues that are just questions. 7 | - Tackle existing issues. Sometimes issues are stuck because they lack information or specificity. Sometimes they need special setup to reproduce. Sometimes they need decision making. 8 | - Improve documentation. Rewrite things that are confusing, fix typos. Ask questions about things you're confused about! 9 | - Report bugs clearly. Include a simple reproduction if possible. If not, be as deliberate and thorough in your description as you can, including code and context. DarkConfig is something of a "be everything" project, unfortunately, so it will have lots of cases where folks are simply using it differently than anyone else ever did and exposing fresh bugs. 10 | - Review pull requests. They generally need reviewing to make sure they fit in with the rest of the project. Not to mention testing that they work and achieve their goals! 11 | - Improve compliance with the style. We have a goal style but fail to meet it. Finding those places and tidying them up will help keep the project clean for the future! 12 | - Help broaden compatibility. We currently support a narrow set of Unity versions, but it would be nice to support more, and also to support other C# platforms. 13 | - Make Dark Skies better. When developers are learning about a project, looking at a real-world example is more instructive than simple contrived demos. The richer and more finished a game Dark Skies becomes, the more competent people will be at using DarkConfig based on its example. This can also provide a motivating impetus to add or change features. 14 | 15 | We'll be more likely to maintain DarkConfig if it's easy, so the more you can help us save time, the more likely we are to make forward progress! 16 | 17 | # Code Contributions 18 | 19 | We welcome code contributions! Please check through this section to make sure that your contribution is as smooth as it can be. 20 | 21 | - Keep in mind the scope of the project. DarkConfig is meant to be flexible and powerful, but it probably shouldn't grow to be a sprawling Django-like framework. It should remain focused on loading configuration files with minimum fuss. 22 | - Please only open one pull request per feature/fix. Omnibus pull requests can be hard to understand. 23 | - Make sure to follow the code style. Indent using 4 spaces, braces in OTBS style except one-line ifs lack newlines or braces, member variables prefixed with m_ and statics with s_, capitalize publics, no unnecessary properties. 24 | - Make sure the new feature is covered by tests. Let's shoot for 100% coverage, every contribution helps! 25 | - Try to maintain backwards compatibility. This just makes it smoother for a large group of people to keep contributing. There are some things that might require breakage, in which case we should create a branch and a DarkConfig 2.0 release. 26 | - Avoid major refactorings. Those can make the contirbution hard to read and understand. 27 | - Improve or maintain performance. DarkConfig ain't never gonna be the fastest config loader out there, but we do have projects that need to load dozens of megabytes of configs in thousands of files and those should remain workable. 28 | - When you contribute code to the project, you implicitly do so under the terms of the DarkConfig LICENSE. Ensure you have the the rights to the code you're contributing. 29 | - Always run all the tests before committing! They're there to check for simple mistakes. See the tests docmentation in the Docs directory for information on how to run them. 30 | 31 | # Areas of Development 32 | 33 | Some areas that currently need thought and/or work: 34 | 35 | More tests! This is *infrastructure* so we want it to be rock-solid. I typically find it difficult to test the runtime of the system; pretty much every method on ConfigFileManager is undertested. It's so annoying to set up integration tests in Unity! The new ConsolePlatform maybe provides a way to make unit tests because we can run coroutines manually. In general though, increasing test coverage, and simplifying test authoring, is always welcome. 36 | 37 | Singletons. Right now DarkConfig is designed as a singleton; you only have one Config. I'm not completely convinced that this is the best thing. Perhaps it should be refactored to be a constructable object, and if a game wants to treat it like a singleton, it's easy enough to just assign the object to a static variable. 38 | 39 | Removing friction. Here's a few rough edges: 40 | - The necessity of creating your own editor script for index generation. Maybe we should configure DarkConfig via a configuration file. Or maybe we can get rid of the index file. We maybe make the example auto-update the index file whenever files on disk change. 41 | - Preloading. It fixed a number of race condition bugs when introduced, so it's definitely good. But maybe it could be cleaner and less obtrusive. 42 | - PostDocs kinda suck in practice. I'd love to wedge a tiny bit more magic into DarkConfig to make my day authoring configs a little easier. 43 | 44 | Compatibility improvements. More Unity versions would be nice. I'm also _pretty_ sure that DarkConfig works on iOS with the .Net 2.0 subset, but it's been a while since I've actually tested it. 45 | 46 | Security. It would be nice if without doing a ton of work we were able to tighten up the security story for DarkConfig, making it suitable to load untrusted files. This will mostly involve the YAML parser. 47 | -------------------------------------------------------------------------------- /DarkConfig.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DarkConfig", "src\DarkConfig\DarkConfig.csproj", "{14D768D9-A27F-4DDA-BED3-D034F1887219}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DarkConfig.Tests", "test\DarkConfig.Tests.csproj", "{629730F0-AE4C-4D13-ACB6-DDB04019158E}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {14D768D9-A27F-4DDA-BED3-D034F1887219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {14D768D9-A27F-4DDA-BED3-D034F1887219}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {14D768D9-A27F-4DDA-BED3-D034F1887219}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {14D768D9-A27F-4DDA-BED3-D034F1887219}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {629730F0-AE4C-4D13-ACB6-DDB04019158E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {629730F0-AE4C-4D13-ACB6-DDB04019158E}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {629730F0-AE4C-4D13-ACB6-DDB04019158E}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {629730F0-AE4C-4D13-ACB6-DDB04019158E}.Release|Any CPU.Build.0 = Release|Any CPU 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Docs/DarkConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/Docs/DarkConfig.png -------------------------------------------------------------------------------- /Docs/docnode.md: -------------------------------------------------------------------------------- 1 | # DocNode 2 | 3 | DocNode is a union type. This means that though as far as C# the language is concerned there is only the one type, DocNode, under the hood it _behaves_ as though it is one of a few types. DocNodes can be Scalar, List, Dictionary, or (rarely) Invalid. Every DocNode has methods that behave like List or Dictionary accessors, but those will only work if the underlying type is right. So before you operate on a DocNode, it makes sense to check the type, using the `Type` property. 4 | 5 | Here's a summary of the DocNode interface. 6 | 7 | ## Type 8 | ```C# 9 | DocNodeType Type { get; } 10 | ``` 11 | 12 | Type of the DocNode: Scalar, List, Dictionary, or Invalid 13 | 14 | ## As 15 | ```C# 16 | T As(); 17 | ``` 18 | 19 | Converts the DocNode to a type T, using the normal parsing rules. For example: `var arr = dn.As()`. Be careful not to call `As()` on the object passed in to the FromDoc function where T is also the registered type of the FromDoc; this will cause an infinite loop. 20 | 21 | ## List Accessor 22 | ```C# 23 | DocNode this[int index] { get; } 24 | ``` 25 | 26 | Access the node as if it was a List. Will throw a DocNodeAccessException if Type is not List. 27 | 28 | ## Dictionary Accessor 29 | ```C# 30 | DocNode this[string key] { get; } 31 | ``` 32 | 33 | Access the node as if it was a Dictionary. Will throw a DocNodeAccessException if Type is not Dictionary. 34 | 35 | ## Count 36 | ```C# 37 | int Count { get; } 38 | ``` 39 | 40 | Number of items in the collection, for both List and Dictionary type. Will throw a DocNodeAccessException if Type is not List or Dictionary. 41 | 42 | ## StringValue 43 | ```C# 44 | string StringValue { get; } 45 | ``` 46 | 47 | Value as a string. Will throw a DocNodeAccessException if Type is not Scalar. 48 | 49 | ## ContainsKey 50 | ```C# 51 | bool ContainsKey(string key); 52 | ``` 53 | 54 | Returns true if the key is in the dictionary. Will throw a DocNodeAccessException if Type is not Dictionary. 55 | 56 | ## Values 57 | ```C# 58 | IEnumerable Values { get; } 59 | ``` 60 | 61 | Iterates over the values of a list. Will throw a DocNodeAccessException if Type is not List. 62 | 63 | ## Pairs 64 | ```C# 65 | IEnumerable> Pairs { get; } 66 | ``` 67 | 68 | Iterates over a the key/value pairs of a dictionary. Will throw a `DocNodeAccessException` if Type is not Dictionary. 69 | 70 | ## SourceInformation 71 | ```C# 72 | string SourceInformation { get; } 73 | ``` 74 | 75 | String describing the position and context in the source format (e.g. line number). Used to print useful error messages when difficulties are encountered parsing. 76 | -------------------------------------------------------------------------------- /Docs/migrating_from_v1.md: -------------------------------------------------------------------------------- 1 | # Migrating from DarkConfig v1 2 | 3 | DarkConfig v2 introduces some breaking API changes. This is a quick guide on migrating from v1 4 | 5 | - `DarkConfig.Config` is now `DarkConfig.Configs` 6 | - `Config.Load()` is now `Configs.ParseFile()` 7 | - `ConfigReifier.Reify()` is now `Configs.Reify()` 8 | - 2D arrays are transposed compared to pre-migration. See: https://github.com/SpryFox/DarkConfig/issues/28 9 | - `DocNode` methods `AsInt()`, `AsFloat()`, `AsString()`, `AsBool()` have been removed. You can either add your own extension methods or change to use `As<>()` 10 | - `index.bytes` is not needed for `FileSource` 11 | - `ConfigFileInfo.Size` is now 64-bits (`long`) 12 | - Logs require the define flag `DC_LOGGING_ENABLED` 13 | 14 | -------------------------------------------------------------------------------- /Docs/sources.md: -------------------------------------------------------------------------------- 1 | # Config Sources 2 | 3 | `ConfigSource` instances provide DarkConfig with a means to find and load config files. DarkConfig provides two built-in source types out of the box that cover most cases, but the `ConfigSource` base class is designed to be extended to support custom data sources for your game. Config sources can optionally support hotloading of configs 4 | 5 | ## Built-In Source Types 6 | 7 | There are two built-in source types: 8 | - `ResourcesSource` loads files from Unity's "Resources" directories. 9 | - `FileSource` loads files from any directory on the filesystem. 10 | 11 | Before working with DarkConfig, you need to provide it with one or more config sources. 12 | 13 | ```C# 14 | // FileSource 15 | 16 | var configsDir = Path.Combine(Directory.GetCurrentDirectory(), "Configs"); 17 | 18 | // load all files with the ".yaml" extension from the given path 19 | Configs.AddSource(new FileSource(configsDir)); 20 | 21 | // load all files with the ".conf" extension from the given path. 22 | Configs.AddSource(new FileSource(configsDir, "conf")) 23 | 24 | // load all files with either the ".yml" or ".yaml" extension from the given path. 25 | Configs.AddSource(new FileSource(configsDir, new[]{"yml", "yaml"})) 26 | 27 | // same as above but also enable file hotloading (disabled by default) 28 | Configs.AddSource(new FileSource(configsDir, new[]{"yml", "yaml"}, hotload:true)) 29 | 30 | 31 | // ResourcesSource (Unity only) 32 | 33 | // load files in the default path: Assets/Resources/Configs 34 | Configs.AddSource(new ResourcesSource()); 35 | 36 | // load files in the path: Assets/Resources/Demo 37 | Configs.AddSource(new ResourcesSource("Demo")); 38 | 39 | // load files in the path: Assets/Resources/Demo with hotloading (disabled by default) enabled. 40 | Configs.AddSource(new ResourcesSource("Demo", hotload:true)); 41 | ``` 42 | 43 | ## Custom Sources 44 | 45 | To provide an additional means of loading config files, you can create a custom `ConfigSource` subclass. Refer to one of the built-in source types for an example of this process. 46 | 47 | There are a few methods and properties you need to provide: 48 | 49 | * `CanHotload`: (required) A bool indicating whether this config source supports hotloading files. 50 | * `StepPreload`: (required) A generator function that loads one config file before yielding null. This allows for both blocking and time-sliced loading. 51 | * `Hotload`: (optional) Called by DarkConfig to detect changes to files that it should hotload. Add the file names of changed configs to the `changedFiles` list parameter to indicate they should be hotloaded. 52 | * `AllFiles`: field that provides the loaded config file data to DarkConfig. `StepPreload` should populate this dictionary with instances of `ConfigFileInfo` mapped to by the config file name (without extension). 53 | -------------------------------------------------------------------------------- /Docs/tests.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | DarkConfig has a number of unit tests and integration tests. These are divided into general DarkConfig tests and Unity-specific tests. 4 | 5 | There is also a demo game, Dark Skies, which can be used to test behavior. To run the game, open and run the "Loader" scene in Unity. Changes to the Whip.bytes card (or any config) should hotload and be visible in the player plane's appearance or behavior. 6 | 7 | ## General Unit Tests 8 | 9 | The unit tests are located in the `test/` directory and are part of the `test/DarkConfig.Tests.csproj` project. They use the nunit framework and you can run them through Rider or Visual Studio. 10 | 11 | ## Unity specific tests 12 | 13 | From within Unity, run them using `Window > Tests Runner`. -------------------------------------------------------------------------------- /Docs/validation.md: -------------------------------------------------------------------------------- 1 | # Validation 2 | 3 | So the designer you work with added a ton of new enemies, but sometimes accidentally forgot to set their color. So now you're wondering why sometimes the map has all these black dots on it. Whoops, might have been nice to have a big old error pointing this subtle bug out! That's what validation is for. 4 | 5 | DarkConfig does two very simple validations: checking for *missing* fields, and *extra* fields. A missing field is one that is in your class, but it's missing from the config file (as in our mainColor example). An extra field is present in the config file but not on the object -- maybe it's a misspelling like "mainColour", or maybe it's left over from a previous generation. 6 | 7 | ```C# 8 | // SampleObject.cs ---- 9 | public class SampleObject { 10 | string field1; 11 | string field2; 12 | } 13 | ``` 14 | ```yaml 15 | # sample_config.bytes ---- 16 | field1: value1 17 | # field2 is missing 18 | field3: value3 # this field is extra 19 | ``` 20 | 21 | When you call Config.Apply, DarkConfig will run these validations and throw ParseExceptions for violations, showing the file and line number. Then you can fix them! 22 | 23 | You can turn on and off validation at many different levels in DarkConfig. 24 | 25 | The precedence of validation is: Field Attribute > Class Attribute > Reify > Global 26 | 27 | ## Global Validation 28 | 29 | Control the default/global validation mode by setting the Config.ConfigOptions enum. This enum has several flags: 30 | 31 | * AllowExtraFields: If set, DarkConfig will not check whether extra fields are present in the config file. 32 | * AllowMissingFields: If set, DarkConfig will not check whether any fields are missing from the config file. 33 | * CaseSensitive: If set, DarkConfig will treat fields as distinct if they differ only in case. 34 | * None: None of the above. DarkConfig will be case-insensitive and will check for missing and extra fields. 35 | 36 | Example: 37 | 38 | // tell DarkConfig to not complain about anything 39 | Config.ConfigOptions = ConfigOptions.AllowExtraFields | ConfigOptions.AllowMissingFields; 40 | 41 | // we can skip some fields but say something if there's an extra field 42 | Config.ConfigOptions = ConfigOptions.AllowMissingFields; 43 | 44 | ## Field Validation 45 | 46 | Set per-field validation with attributes. 47 | 48 | * The `ConfigMandatory` attribute means the field cannot go missing. This overrides any global setting of `ConfigOptions.AllowMissingFields`. 49 | * `ConfigAllowMissing` makes its field skippable, it will not give an exception if not present in the config file. This overrides a global setting that lacks `ConfigOptions.AllowMissingFields`. 50 | * ConfigIgnore is special: it causes DarkConfig to ignore any validation on the field and _also_ never set it. It will be as though the field doesn't exist on the class. This is useful when you want to have strict validation on all other fields but have a few fields that are not set from config files. 51 | 52 | 53 | ```C# 54 | class AttributesClass { 55 | [ConfigMandatory] 56 | public int field1 = -1; // will complain if this field is not in config 57 | 58 | [ConfigAllowMissing] 59 | public string field2 = "initial"; // will happily tolerate this field being missing 60 | 61 | [ConfigIgnore] 62 | public bool field3 = false; // will not set this field 63 | } 64 | ``` 65 | 66 | ## Class Validation 67 | 68 | Change DarkConfig's validation on a per-class basis with attributes. 69 | 70 | You can apply ConfigMandatory or ConfigAllowMissing to any class, where they apply to all fields. 71 | 72 | As a special case, classes derived from MonoBehaviour have an implicit ConfigAllowMissing. This is because the MonoBehaviour class has a ton of fields that you don't control and don't want to set. 73 | 74 | 75 | ## Reify Validation 76 | 77 | You can set ConfigOptions per call to Reify. This overrides the global setting for the duration of the call. 78 | 79 | Config.Reify("Configs/testconfig.bytes", ref obj, ConfigOptions.CaseSensitive | ConfigOptions.AllowExtraFields); 80 | 81 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017, Spry Fox LLC 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | If the redistribution is a game, the game must include "Thanks to Spry Fox for DarkConfig" (or very similar language) within the game's credits. 10 | 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /THANKS.md: -------------------------------------------------------------------------------- 1 | THANKS 2 | ======= 3 | 4 | This file contains the list of folks who have helped with the development of DarkConfig in one way or another. This list is not ordered in any way except perhaps loosely chronologically. 5 | 6 | - Spry Fox - the cradle that nutured this creation 7 | - Alex Holkner - created a system that read google spreadsheets into Unity games, which was the seed idea that inspired the creation of DarkConfig 8 | - Alex Jaffe - many illuminating conversations about the design of DarkConfig in the early stages 9 | - Daniel Cook - enthusiastic champion and power designer, DarkConfig is designed to make him happy 10 | - Andrew Fray - contributing bug fixes and feedback 11 | - David Edery - supporting the project the whole way 12 | - Rafael Cobra Teske - many bug fixes, contributions to console support 13 | - JJ Richards - lots of super detailed feedback 14 | - Cristian Soulos - contributing bug fixes and feedback 15 | 16 | If you are missing from the list and think you should be on it, please be assured it's merely an oversight! Let me know. -------------------------------------------------------------------------------- /demo/Assets/DarkConfig.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca58de63c989f9646843644faba40d84 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2c17f306770a443082f271fb23f74ea 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/Editor/EditorUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEditor; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | namespace DarkConfig { 8 | public static class EditorMenus { 9 | [MenuItem ("Assets/DarkConfig/Autogenerate Index")] 10 | static void MenuGenerateIndex() { 11 | EditorUtils.GenerateIndex("Resources/Configs"); 12 | AssetDatabase.Refresh(); 13 | } 14 | } 15 | 16 | public class EditorUtils { 17 | static readonly string[] INDEX_FILE_HEADER = { 18 | "# automatically generated DarkConfig index file", 19 | "# DO NOT EDIT THIS MANUALLY", 20 | "# Instead, run Assets > DarkConfig > Autogenerate Index", 21 | "#", 22 | "---" 23 | }; 24 | 25 | public static List FindConfigFiles(string baseDir = "/Resources/Configs") { 26 | var retval = new List(); 27 | var absPath = new DirectoryInfo(Application.dataPath + baseDir); 28 | var absPathSlashed = absPath.FullName.Replace("\\", "/"); 29 | 30 | var fileInfo = absPath.GetFiles("*.bytes", SearchOption.AllDirectories); 31 | foreach (var file in fileInfo) { 32 | var dirName = file.DirectoryName.Replace("\\", "/"); 33 | 34 | var relativeToBase = dirName.Replace(absPathSlashed, "").Trim('/', '\\'); 35 | var completePath = (relativeToBase + "/" + file.Name).Trim('/', '\\'); 36 | retval.Add(completePath); 37 | } 38 | 39 | retval.Sort((a, b) => { 40 | var slashesA = CountCharacter('/', a); 41 | var slashesB = CountCharacter('/', b); 42 | if (slashesA != slashesB) { 43 | return slashesA.CompareTo(slashesB); 44 | } 45 | 46 | return string.Compare(a, b, StringComparison.Ordinal); 47 | }); 48 | 49 | return retval; 50 | } 51 | 52 | /// 53 | /// Counts the instances of a character in a string 54 | /// 55 | /// character to count 56 | /// string to search within 57 | /// count of 58 | static int CountCharacter(char c, string s) { 59 | int count = 0; 60 | foreach (char t in s) { 61 | if (t == c) { 62 | count++; 63 | } 64 | } 65 | 66 | return count; 67 | } 68 | 69 | /// 70 | /// Writes the list of files to the index file. 71 | /// The files are expected to be listed relative to a Resources directory. 72 | /// The indexFile is specified relative to the Assets directory. It must also be in a resources directory. 73 | /// E.g. "Assets/Resources/Configs/index.bytes" 74 | /// 75 | /// 76 | /// 77 | /// 78 | public static int WriteIndexFile(List filesInIndex, string indexFile) { 79 | int resourcesIdx = indexFile.IndexOf("Resources/", StringComparison.Ordinal); 80 | if (resourcesIdx < 0) { 81 | Debug.LogError($"Index file {indexFile} should have Resources directory in its path"); 82 | return 0; 83 | } 84 | 85 | string relToResources = indexFile.Substring(resourcesIdx + "Resources/".Length); 86 | 87 | string indexPath = Application.dataPath + "/" + indexFile; 88 | 89 | // create directory if necessary 90 | var indexDir = new FileInfo(indexPath).Directory; 91 | if (!indexDir.Exists) { 92 | indexDir.Create(); 93 | } 94 | 95 | int totalWritten = 0; 96 | 97 | // write the header into the file 98 | using (var writer = new StreamWriter(indexPath, false)) { 99 | // Write file header 100 | foreach (string headerLine in INDEX_FILE_HEADER) { 101 | writer.WriteLine(headerLine); 102 | } 103 | 104 | // write all the index entries into the file 105 | foreach (string file in filesInIndex) { 106 | // skip over index file itself, it's likely to be in the list already 107 | if (file == relToResources) { 108 | continue; 109 | } 110 | writer.WriteLine("- " + file); 111 | totalWritten++; 112 | } 113 | } 114 | 115 | File.SetLastWriteTime(indexPath, DateTime.Now); 116 | return totalWritten; 117 | } 118 | 119 | public static void GenerateIndex(string baseDir) { 120 | var indexFilePath = baseDir + "/index.bytes"; 121 | Debug.Log("Generating Index at " + indexFilePath + " using files in directory " + baseDir); 122 | var configs = FindConfigFiles(baseDir); 123 | // rename to short names 124 | for (int configIndex = 0; configIndex < configs.Count; configIndex++) { 125 | configs[configIndex] = configs[configIndex] 126 | .Replace(baseDir + "/", "") 127 | .Replace(".bytes", ""); 128 | } 129 | 130 | var total = WriteIndexFile(configs, indexFilePath); 131 | Debug.Log("Wrote " + total + " configs to index"); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/Editor/EditorUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 392929c4109b341d0a2c5fc1b4f340b4 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/ResourcesSource.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | 6 | namespace DarkConfig { 7 | /// loads configs from a Unity Resources directory 8 | /// 9 | /// since we can't check the timestamp on the files, it has to read them in in their 10 | /// entirety to see whether to hotload them 11 | public class ResourcesSource : ConfigSource { 12 | const string INDEX_FILENAME = "index"; 13 | 14 | public override bool CanHotload { get; } 15 | 16 | public ResourcesSource(string baseDir = "Configs", bool hotload = false) { 17 | this.baseDir = baseDir; 18 | CanHotload = hotload && Application.isEditor; 19 | } 20 | 21 | public override IEnumerable StepPreload() { 22 | AllFiles.Clear(); 23 | filesList.Clear(); 24 | 25 | // Load the index file. 26 | indexFile = ReadFile(INDEX_FILENAME); 27 | if (indexFile == null) { 28 | throw new($"Index file is missing at Resources path {INDEX_FILENAME}."); 29 | } 30 | 31 | // Load all the files. 32 | foreach (var nameNode in indexFile.Parsed.Values) { 33 | string filename = nameNode.StringValue; 34 | filesList.Add(filename); 35 | if (filename != "index") { 36 | AllFiles[filename] = ReadFile(filename); 37 | yield return null; 38 | } 39 | } 40 | } 41 | 42 | public override void Hotload(List changedFiles) { 43 | // First try to load the index in case any files were added or removed. 44 | var newIndex = ReadFile(INDEX_FILENAME); 45 | if (newIndex == null) { 46 | throw new($"Index file is missing at Resources path {INDEX_FILENAME}."); 47 | } 48 | 49 | if (newIndex.Checksum != indexFile.Checksum) { 50 | // Index has changed, possibly have added or removed files from the index. 51 | // TODO Smart update, don't just toss the whole list and start from scratch. 52 | foreach (object _ in StepPreload()) { } 53 | changedFiles.AddRange(filesList); 54 | } else { 55 | // Index hasn't changed. Check each file. 56 | foreach (string file in filesList) { 57 | var newFile = ReadFile(file); 58 | if (newFile.Checksum == AllFiles[file].Checksum) { 59 | continue; 60 | } 61 | AllFiles[file] = newFile; 62 | changedFiles.Add(file); 63 | } 64 | } 65 | } 66 | 67 | public override string ToString() { 68 | return $"ResourcesSource({baseDir})"; 69 | } 70 | 71 | ///////////////////////////////////////////////// 72 | 73 | ConfigFileInfo indexFile; 74 | readonly List filesList = new List(); 75 | readonly string baseDir; 76 | 77 | ///////////////////////////////////////////////// 78 | 79 | ConfigFileInfo ReadFile(string filename) { 80 | // Get the full resources path for the file. 81 | string path = baseDir + "/" + filename; 82 | 83 | // Remove extension if one is specified. 84 | path = System.IO.Path.ChangeExtension(path, null); 85 | 86 | var asset = Resources.Load(path); 87 | if (asset == null) { 88 | return null; 89 | } 90 | 91 | return new( 92 | name: filename, 93 | checksum: Internal.ChecksumUtils.Checksum(asset.text), 94 | size: asset.text.Length, 95 | // It's not easy to get a modified timestamp on a resources file, so just set it to the 96 | // default DateTime value. We'll instead rely on checksums to detect differences that need hotloading. 97 | modified: new(), 98 | parsed: Configs.ParseString(asset.text, filename)); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/ResourcesSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdbdcb43d4a8749758059c0f19ada288 3 | timeCreated: 1462915515 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/UnityPlatform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace DarkConfig { 5 | public static class UnityPlatform { 6 | public static void Setup(bool hotloading = false) { 7 | UnityTypeReifiers.RegisterAll(); 8 | Configs.LogCallback = Log; 9 | 10 | if (hotloading) { 11 | SetupHotloadingManager(); 12 | } 13 | } 14 | 15 | static void Log(LogVerbosity verbosity, string message) { 16 | switch (verbosity) { 17 | case LogVerbosity.Warn: Debug.LogWarning(message); break; 18 | case LogVerbosity.Info: Debug.Log(message); break; 19 | default: throw new ArgumentOutOfRangeException(nameof(verbosity), verbosity, null); 20 | } 21 | } 22 | 23 | private static GameObject hotloadingManagerInstance = null; 24 | static void SetupHotloadingManager() { 25 | if (hotloadingManagerInstance != null) { 26 | return; 27 | } 28 | 29 | hotloadingManagerInstance = new GameObject("DarkConfigHotloadingManager"); 30 | hotloadingManagerInstance.AddComponent(); 31 | } 32 | 33 | class HotloadingManager : MonoBehaviour { 34 | void Awake() { 35 | DontDestroyOnLoad(gameObject); 36 | } 37 | 38 | void Update() { 39 | Configs.Update(Time.deltaTime); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/UnityPlatform.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d338fa5147d441c5a15d75d36674b3f 3 | timeCreated: 1475697181 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/DarkConfig/UnityTypeReifiers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 509811cd1f99c4529a81cbec8e44483b 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68805e3e4576d45b1bfbd6c9baa37348 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7927d779e32e4ae3a88a9082013d029 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/Bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/Bullet.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/Bullet.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a67e64f9fbce445ab91e35154d482a51 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 9 47 | spritePivot: {x: 0.5104232, y: 0.6855326} 48 | spritePixelsToUnits: 25 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/City_Repeat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/City_Repeat.jpg -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/City_Repeat.jpg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba92ef487ba9f4c868f20245eda29556 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 0 42 | textureType: 0 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/Clouds_Repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/Clouds_Repeat.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/Clouds_Repeat.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7d176ee0e33a94f348fa3da0133ad559 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 1 42 | textureType: 0 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/circle.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/circle.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 699c214982c804fec985eb5e2dd904ba 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/fuselage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/fuselage.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/fuselage.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c50995914c97f40d9bfb8de748f41af5 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/plane.svg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c5016da2ebde449b4be5490d7df02f6a 3 | timeCreated: 1487532903 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/plus.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/plus.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c485a2c8da304368b3399fcce9ed746 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/puff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/puff.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/puff.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83779aa4fabb540a68af6e9981c5a89c 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 1 42 | textureType: 0 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/stabilizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/stabilizer.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/stabilizer.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 370489f73b8ca42b7aefad3ea4335cfa 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 9 47 | spritePivot: {x: 0.9724112, y: 0.4935096} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/wing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpryFox/DarkConfig/49890c460fff5dbfdab9736baaf32af9bba1709c/demo/Assets/Demo/Art/wing.png -------------------------------------------------------------------------------- /demo/Assets/Demo/Art/wing.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: efdcfb877781c465ba7925e128bed459 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 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: -1 31 | maxTextureSize: 1024 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 5 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 1 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 1024 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c61b9626853e4b0e98efe1f852c25ac 3 | folderAsset: yes 4 | timeCreated: 1452660066 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/City.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 3 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: City 10 | m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: [] 12 | m_CustomRenderQueue: -1 13 | m_SavedProperties: 14 | serializedVersion: 2 15 | m_TexEnvs: 16 | data: 17 | first: 18 | name: _MainTex 19 | second: 20 | m_Texture: {fileID: 2800000, guid: ba92ef487ba9f4c868f20245eda29556, type: 3} 21 | m_Scale: {x: 4, y: 4} 22 | m_Offset: {x: 0, y: 0} 23 | data: 24 | first: 25 | name: _Illum 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | m_Floats: 31 | data: 32 | first: 33 | name: _EmissionLM 34 | second: 0 35 | m_Colors: 36 | data: 37 | first: 38 | name: _Color 39 | second: {r: 1, g: 1, b: 1, a: 1} 40 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/City.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d7080b5bd26a4eb9ae1b366ea572675 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Clouds.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 3 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Clouds 10 | m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: [] 12 | m_CustomRenderQueue: -1 13 | m_SavedProperties: 14 | serializedVersion: 2 15 | m_TexEnvs: 16 | data: 17 | first: 18 | name: _MainTex 19 | second: 20 | m_Texture: {fileID: 2800000, guid: 7d176ee0e33a94f348fa3da0133ad559, type: 3} 21 | m_Scale: {x: 7, y: 7} 22 | m_Offset: {x: 0, y: 0} 23 | data: 24 | first: 25 | name: _Illum 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | m_Floats: 31 | data: 32 | first: 33 | name: _EmissionLM 34 | second: 0 35 | m_Colors: 36 | data: 37 | first: 38 | name: _Color 39 | second: {r: .33088237, g: .324002981, b: .231131077, a: 1} 40 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Clouds.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da99b5f5a9d4f43089b7baa8e11ffd6b 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Clouds2.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 3 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Clouds2 10 | m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: [] 12 | m_CustomRenderQueue: -1 13 | m_SavedProperties: 14 | serializedVersion: 2 15 | m_TexEnvs: 16 | data: 17 | first: 18 | name: _MainTex 19 | second: 20 | m_Texture: {fileID: 2800000, guid: 7d176ee0e33a94f348fa3da0133ad559, type: 3} 21 | m_Scale: {x: 5, y: 5} 22 | m_Offset: {x: 0, y: 0} 23 | data: 24 | first: 25 | name: _Illum 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | m_Floats: 31 | data: 32 | first: 33 | name: _EmissionLM 34 | second: 0 35 | m_Colors: 36 | data: 37 | first: 38 | name: _Color 39 | second: {r: .20588237, g: .20588237, b: .20588237, a: 1} 40 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Clouds2.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fc6a0f788423249f1921dfcc8ef8e08e 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Puff.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 3 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Puff 10 | m_Shader: {fileID: 203, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: [] 12 | m_CustomRenderQueue: -1 13 | m_SavedProperties: 14 | serializedVersion: 2 15 | m_TexEnvs: 16 | data: 17 | first: 18 | name: _MainTex 19 | second: 20 | m_Texture: {fileID: 2800000, guid: 83779aa4fabb540a68af6e9981c5a89c, type: 3} 21 | m_Scale: {x: 1, y: 1} 22 | m_Offset: {x: 0, y: 0} 23 | data: 24 | first: 25 | name: _Illum 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | m_Floats: 31 | data: 32 | first: 33 | name: _EmissionLM 34 | second: 0 35 | data: 36 | first: 37 | name: _InvFade 38 | second: 1 39 | m_Colors: 40 | data: 41 | first: 42 | name: _Color 43 | second: {r: 1, g: 1, b: 1, a: 1} 44 | data: 45 | first: 46 | name: _TintColor 47 | second: {r: 1, g: 1, b: 1, a: .501960814} 48 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/Puff.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c85f01521d4342ff879d9d991cc48e6 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/ShotFireParticle.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ShotFireParticle 10 | m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 5 13 | m_CustomRenderQueue: 3000 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | data: 19 | first: 20 | name: _MainTex 21 | second: 22 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | data: 26 | first: 27 | name: _BumpMap 28 | second: 29 | m_Texture: {fileID: 0} 30 | m_Scale: {x: 1, y: 1} 31 | m_Offset: {x: 0, y: 0} 32 | data: 33 | first: 34 | name: _DetailNormalMap 35 | second: 36 | m_Texture: {fileID: 0} 37 | m_Scale: {x: 1, y: 1} 38 | m_Offset: {x: 0, y: 0} 39 | data: 40 | first: 41 | name: _ParallaxMap 42 | second: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | data: 47 | first: 48 | name: _OcclusionMap 49 | second: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | data: 54 | first: 55 | name: _EmissionMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | data: 61 | first: 62 | name: _DetailMask 63 | second: 64 | m_Texture: {fileID: 0} 65 | m_Scale: {x: 1, y: 1} 66 | m_Offset: {x: 0, y: 0} 67 | data: 68 | first: 69 | name: _DetailAlbedoMap 70 | second: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | data: 75 | first: 76 | name: _MetallicGlossMap 77 | second: 78 | m_Texture: {fileID: 0} 79 | m_Scale: {x: 1, y: 1} 80 | m_Offset: {x: 0, y: 0} 81 | m_Floats: 82 | data: 83 | first: 84 | name: _SrcBlend 85 | second: 1 86 | data: 87 | first: 88 | name: _DstBlend 89 | second: 0 90 | data: 91 | first: 92 | name: _Cutoff 93 | second: .5 94 | data: 95 | first: 96 | name: _InvFade 97 | second: 1 98 | data: 99 | first: 100 | name: _Parallax 101 | second: .0199999996 102 | data: 103 | first: 104 | name: _ZWrite 105 | second: 1 106 | data: 107 | first: 108 | name: _Glossiness 109 | second: .5 110 | data: 111 | first: 112 | name: _BumpScale 113 | second: 1 114 | data: 115 | first: 116 | name: _OcclusionStrength 117 | second: 1 118 | data: 119 | first: 120 | name: _DetailNormalMapScale 121 | second: 1 122 | data: 123 | first: 124 | name: _UVSec 125 | second: 0 126 | data: 127 | first: 128 | name: _Mode 129 | second: 0 130 | data: 131 | first: 132 | name: _Metallic 133 | second: 0 134 | m_Colors: 135 | data: 136 | first: 137 | name: _EmissionColor 138 | second: {r: 0, g: 0, b: 0, a: 1} 139 | data: 140 | first: 141 | name: _Color 142 | second: {r: 1, g: 1, b: 1, a: 1} 143 | data: 144 | first: 145 | name: _TintColor 146 | second: {r: 1, g: 1, b: 1, a: 1} 147 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Material/ShotFireParticle.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f121850699ab842d7a75e4153c5da46f 3 | timeCreated: 1452474782 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e99c20d66d1b4ed0aa763991b030643 3 | folderAsset: yes 4 | timeCreated: 1452659954 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Bullet.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &100000 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 400000} 11 | - 212: {fileID: 21200000} 12 | - 58: {fileID: 5800000} 13 | - 114: {fileID: 11400000} 14 | - 50: {fileID: 5000000} 15 | m_Layer: 0 16 | m_Name: Bullet 17 | m_TagString: Untagged 18 | m_Icon: {fileID: 0} 19 | m_NavMeshLayer: 0 20 | m_StaticEditorFlags: 0 21 | m_IsActive: 1 22 | --- !u!4 &400000 23 | Transform: 24 | m_ObjectHideFlags: 1 25 | m_PrefabParentObject: {fileID: 0} 26 | m_PrefabInternal: {fileID: 100100000} 27 | m_GameObject: {fileID: 100000} 28 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 29 | m_LocalPosition: {x: -24.0824509, y: 28.2398224, z: 0} 30 | m_LocalScale: {x: 1, y: 1, z: 1} 31 | m_Children: [] 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | --- !u!50 &5000000 35 | Rigidbody2D: 36 | serializedVersion: 2 37 | m_ObjectHideFlags: 1 38 | m_PrefabParentObject: {fileID: 0} 39 | m_PrefabInternal: {fileID: 100100000} 40 | m_GameObject: {fileID: 100000} 41 | m_Mass: 1 42 | m_LinearDrag: 0 43 | m_AngularDrag: 0 44 | m_GravityScale: 0 45 | m_IsKinematic: 0 46 | m_Interpolate: 0 47 | m_SleepingMode: 1 48 | m_CollisionDetection: 1 49 | m_Constraints: 4 50 | --- !u!58 &5800000 51 | CircleCollider2D: 52 | m_ObjectHideFlags: 1 53 | m_PrefabParentObject: {fileID: 0} 54 | m_PrefabInternal: {fileID: 100100000} 55 | m_GameObject: {fileID: 100000} 56 | m_Enabled: 1 57 | m_Material: {fileID: 0} 58 | m_IsTrigger: 1 59 | m_UsedByEffector: 0 60 | m_Offset: {x: 0, y: 0} 61 | serializedVersion: 2 62 | m_Radius: .300000012 63 | --- !u!114 &11400000 64 | MonoBehaviour: 65 | m_ObjectHideFlags: 1 66 | m_PrefabParentObject: {fileID: 0} 67 | m_PrefabInternal: {fileID: 100100000} 68 | m_GameObject: {fileID: 100000} 69 | m_Enabled: 1 70 | m_EditorHideFlags: 0 71 | m_Script: {fileID: 11500000, guid: 75c0ac8114f2e4a4f8f0565b350c5183, type: 3} 72 | m_Name: 73 | m_EditorClassIdentifier: 74 | Damage: 0 75 | Speed: 0 76 | HitPrefab: {fileID: 100002, guid: e0efc93d67d144caba51a4eca4d6ea12, type: 2} 77 | Firer: {fileID: 0} 78 | --- !u!212 &21200000 79 | SpriteRenderer: 80 | m_ObjectHideFlags: 1 81 | m_PrefabParentObject: {fileID: 0} 82 | m_PrefabInternal: {fileID: 100100000} 83 | m_GameObject: {fileID: 100000} 84 | m_Enabled: 1 85 | m_CastShadows: 0 86 | m_ReceiveShadows: 0 87 | m_Materials: 88 | - {fileID: 10754, guid: 0000000000000000e000000000000000, type: 0} 89 | m_SubsetIndices: 90 | m_StaticBatchRoot: {fileID: 0} 91 | m_UseLightProbes: 0 92 | m_ReflectionProbeUsage: 0 93 | m_ProbeAnchor: {fileID: 0} 94 | m_ScaleInLightmap: 1 95 | m_PreserveUVs: 0 96 | m_IgnoreNormalsForChartDetection: 0 97 | m_ImportantGI: 0 98 | m_MinimumChartSize: 4 99 | m_AutoUVMaxDistance: .5 100 | m_AutoUVMaxAngle: 89 101 | m_LightmapParameters: {fileID: 0} 102 | m_SortingLayerID: 0 103 | m_SortingOrder: 0 104 | m_Sprite: {fileID: 21300000, guid: a67e64f9fbce445ab91e35154d482a51, type: 3} 105 | m_Color: {r: 1, g: 1, b: 1, a: 1} 106 | --- !u!1001 &100100000 107 | Prefab: 108 | m_ObjectHideFlags: 1 109 | serializedVersion: 2 110 | m_Modification: 111 | m_TransformParent: {fileID: 0} 112 | m_Modifications: [] 113 | m_RemovedComponents: [] 114 | m_ParentPrefab: {fileID: 0} 115 | m_RootGameObject: {fileID: 100000} 116 | m_IsPrefabParent: 1 117 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Bullet.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8303d936d7f9b42f58a0f2e360412a31 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/BulletHitFX.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0efc93d67d144caba51a4eca4d6ea12 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Enemy.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &100000 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 400000} 11 | - 114: {fileID: 11400002} 12 | - 114: {fileID: 11400000} 13 | - 50: {fileID: 5000000} 14 | m_Layer: 0 15 | m_Name: Enemy 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!4 &400000 22 | Transform: 23 | m_ObjectHideFlags: 1 24 | m_PrefabParentObject: {fileID: 0} 25 | m_PrefabInternal: {fileID: 100100000} 26 | m_GameObject: {fileID: 100000} 27 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 28 | m_LocalPosition: {x: 17.6522179, y: 0, z: 0} 29 | m_LocalScale: {x: 1, y: 1, z: 1} 30 | m_Children: [] 31 | m_Father: {fileID: 0} 32 | m_RootOrder: 0 33 | --- !u!50 &5000000 34 | Rigidbody2D: 35 | serializedVersion: 2 36 | m_ObjectHideFlags: 1 37 | m_PrefabParentObject: {fileID: 0} 38 | m_PrefabInternal: {fileID: 100100000} 39 | m_GameObject: {fileID: 100000} 40 | m_Mass: 1 41 | m_LinearDrag: 0 42 | m_AngularDrag: 0 43 | m_GravityScale: 0 44 | m_IsKinematic: 1 45 | m_Interpolate: 0 46 | m_SleepingMode: 1 47 | m_CollisionDetection: 0 48 | m_Constraints: 0 49 | --- !u!114 &11400000 50 | MonoBehaviour: 51 | m_ObjectHideFlags: 1 52 | m_PrefabParentObject: {fileID: 0} 53 | m_PrefabInternal: {fileID: 100100000} 54 | m_GameObject: {fileID: 100000} 55 | m_Enabled: 1 56 | m_EditorHideFlags: 0 57 | m_Script: {fileID: 11500000, guid: e746dc99bf5984be5abc08aec0e62d4c, type: 3} 58 | m_Name: 59 | m_EditorClassIdentifier: 60 | Controller: {fileID: 11400002} 61 | PickupPrefab: {fileID: 400000, guid: 95671f6452fc34383a438f7ea4d1448f, type: 2} 62 | --- !u!114 &11400002 63 | MonoBehaviour: 64 | m_ObjectHideFlags: 1 65 | m_PrefabParentObject: {fileID: 0} 66 | m_PrefabInternal: {fileID: 100100000} 67 | m_GameObject: {fileID: 100000} 68 | m_Enabled: 1 69 | m_EditorHideFlags: 0 70 | m_Script: {fileID: 11500000, guid: d792d93ca589c474196eb88a2f1ad3fd, type: 3} 71 | m_Name: 72 | m_EditorClassIdentifier: 73 | RotationCommand: 0 74 | IsFiring: 0 75 | Throttle: 1 76 | HitPoints: 0 77 | MaxHitPoints: 0 78 | BulletPrefab: {fileID: 400000, guid: 8303d936d7f9b42f58a0f2e360412a31, type: 2} 79 | ViewPrefab: {fileID: 400010, guid: 753a9c9756a404422b47e71325b95822, type: 2} 80 | ExplosionPrefab: {fileID: 150164, guid: a61f344ddc6c9416a97212247cfe3afa, type: 2} 81 | ShotFireFXPrefab: {fileID: 112258, guid: cd082a60c9ec5414eb443362175370a9, type: 2} 82 | View: {fileID: 0} 83 | --- !u!1001 &100100000 84 | Prefab: 85 | m_ObjectHideFlags: 1 86 | serializedVersion: 2 87 | m_Modification: 88 | m_TransformParent: {fileID: 0} 89 | m_Modifications: 90 | - target: {fileID: 0} 91 | propertyPath: ExplosionPrefab 92 | value: 93 | objectReference: {fileID: 150164, guid: a61f344ddc6c9416a97212247cfe3afa, type: 2} 94 | - target: {fileID: 0} 95 | propertyPath: ShotFireFXPrefab 96 | value: 97 | objectReference: {fileID: 112258, guid: cd082a60c9ec5414eb443362175370a9, type: 2} 98 | m_RemovedComponents: [] 99 | m_ParentPrefab: {fileID: 0} 100 | m_RootGameObject: {fileID: 100000} 101 | m_IsPrefabParent: 1 102 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Enemy.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8527b6abad74f496383a24951dacb910 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Explosion.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a61f344ddc6c9416a97212247cfe3afa 3 | timeCreated: 1452410711 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Pickup.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 95671f6452fc34383a438f7ea4d1448f 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/PlaneView.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 753a9c9756a404422b47e71325b95822 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Player.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &100000 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 400000} 11 | - 114: {fileID: 11400000} 12 | - 114: {fileID: 11400002} 13 | m_Layer: 0 14 | m_Name: Player 15 | m_TagString: Player 16 | m_Icon: {fileID: 0} 17 | m_NavMeshLayer: 0 18 | m_StaticEditorFlags: 0 19 | m_IsActive: 1 20 | --- !u!4 &400000 21 | Transform: 22 | m_ObjectHideFlags: 1 23 | m_PrefabParentObject: {fileID: 0} 24 | m_PrefabInternal: {fileID: 100100000} 25 | m_GameObject: {fileID: 100000} 26 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 27 | m_LocalPosition: {x: 0, y: 0, z: 0} 28 | m_LocalScale: {x: 1, y: 1, z: 1} 29 | m_Children: [] 30 | m_Father: {fileID: 0} 31 | m_RootOrder: 0 32 | --- !u!114 &11400000 33 | MonoBehaviour: 34 | m_ObjectHideFlags: 1 35 | m_PrefabParentObject: {fileID: 0} 36 | m_PrefabInternal: {fileID: 100100000} 37 | m_GameObject: {fileID: 100000} 38 | m_Enabled: 1 39 | m_EditorHideFlags: 0 40 | m_Script: {fileID: 11500000, guid: 74880b4d8c9c547a59e921a550dbe9ea, type: 3} 41 | m_Name: 42 | m_EditorClassIdentifier: 43 | StartingCard: 44 | Controller: {fileID: 11400002} 45 | --- !u!114 &11400002 46 | MonoBehaviour: 47 | m_ObjectHideFlags: 1 48 | m_PrefabParentObject: {fileID: 0} 49 | m_PrefabInternal: {fileID: 100100000} 50 | m_GameObject: {fileID: 100000} 51 | m_Enabled: 1 52 | m_EditorHideFlags: 0 53 | m_Script: {fileID: 11500000, guid: d792d93ca589c474196eb88a2f1ad3fd, type: 3} 54 | m_Name: 55 | m_EditorClassIdentifier: 56 | RotationCommand: 0 57 | IsFiring: 0 58 | Throttle: 1 59 | HitPoints: 0 60 | MaxHitPoints: 0 61 | BulletPrefab: {fileID: 400000, guid: 8303d936d7f9b42f58a0f2e360412a31, type: 2} 62 | ViewPrefab: {fileID: 400010, guid: 753a9c9756a404422b47e71325b95822, type: 2} 63 | ExplosionPrefab: {fileID: 150164, guid: a61f344ddc6c9416a97212247cfe3afa, type: 2} 64 | ShotFireFXPrefab: {fileID: 112258, guid: cd082a60c9ec5414eb443362175370a9, type: 2} 65 | View: {fileID: 0} 66 | --- !u!1001 &100100000 67 | Prefab: 68 | m_ObjectHideFlags: 1 69 | serializedVersion: 2 70 | m_Modification: 71 | m_TransformParent: {fileID: 0} 72 | m_Modifications: 73 | - target: {fileID: 0} 74 | propertyPath: ExplosionPrefab 75 | value: 76 | objectReference: {fileID: 150164, guid: a61f344ddc6c9416a97212247cfe3afa, type: 2} 77 | - target: {fileID: 0} 78 | propertyPath: m_TagString 79 | value: Player 80 | objectReference: {fileID: 0} 81 | - target: {fileID: 0} 82 | propertyPath: ShotFireFXPrefab 83 | value: 84 | objectReference: {fileID: 112258, guid: cd082a60c9ec5414eb443362175370a9, type: 2} 85 | m_RemovedComponents: [] 86 | m_ParentPrefab: {fileID: 0} 87 | m_RootGameObject: {fileID: 100000} 88 | m_IsPrefabParent: 1 89 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Player.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c37ec5de83b64fe8a6082ccc59ab1b3 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/ShotFireFX.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd082a60c9ec5414eb443362175370a9 3 | timeCreated: 1452474579 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Title.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &104874 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 450926} 11 | m_Layer: 0 12 | m_Name: Title 13 | m_TagString: Untagged 14 | m_Icon: {fileID: 0} 15 | m_NavMeshLayer: 0 16 | m_StaticEditorFlags: 0 17 | m_IsActive: 1 18 | --- !u!1 &182930 19 | GameObject: 20 | m_ObjectHideFlags: 0 21 | m_PrefabParentObject: {fileID: 0} 22 | m_PrefabInternal: {fileID: 100100000} 23 | serializedVersion: 4 24 | m_Component: 25 | - 4: {fileID: 488126} 26 | - 23: {fileID: 2341492} 27 | - 102: {fileID: 10256288} 28 | m_Layer: 0 29 | m_Name: Title Text 30 | m_TagString: Untagged 31 | m_Icon: {fileID: 0} 32 | m_NavMeshLayer: 0 33 | m_StaticEditorFlags: 0 34 | m_IsActive: 1 35 | --- !u!1 &189376 36 | GameObject: 37 | m_ObjectHideFlags: 0 38 | m_PrefabParentObject: {fileID: 0} 39 | m_PrefabInternal: {fileID: 100100000} 40 | serializedVersion: 4 41 | m_Component: 42 | - 4: {fileID: 486094} 43 | - 23: {fileID: 2383948} 44 | - 102: {fileID: 10283204} 45 | m_Layer: 0 46 | m_Name: Subtitle 47 | m_TagString: Untagged 48 | m_Icon: {fileID: 0} 49 | m_NavMeshLayer: 0 50 | m_StaticEditorFlags: 0 51 | m_IsActive: 1 52 | --- !u!4 &450926 53 | Transform: 54 | m_ObjectHideFlags: 1 55 | m_PrefabParentObject: {fileID: 0} 56 | m_PrefabInternal: {fileID: 100100000} 57 | m_GameObject: {fileID: 104874} 58 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 59 | m_LocalPosition: {x: 0, y: 0, z: 0} 60 | m_LocalScale: {x: 1, y: 1, z: 1} 61 | m_Children: 62 | - {fileID: 488126} 63 | - {fileID: 486094} 64 | m_Father: {fileID: 0} 65 | m_RootOrder: 0 66 | --- !u!4 &486094 67 | Transform: 68 | m_ObjectHideFlags: 1 69 | m_PrefabParentObject: {fileID: 0} 70 | m_PrefabInternal: {fileID: 100100000} 71 | m_GameObject: {fileID: 189376} 72 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 73 | m_LocalPosition: {x: 0, y: -8.5, z: 0} 74 | m_LocalScale: {x: 1, y: 1, z: 1} 75 | m_Children: [] 76 | m_Father: {fileID: 450926} 77 | m_RootOrder: 1 78 | --- !u!4 &488126 79 | Transform: 80 | m_ObjectHideFlags: 1 81 | m_PrefabParentObject: {fileID: 0} 82 | m_PrefabInternal: {fileID: 100100000} 83 | m_GameObject: {fileID: 182930} 84 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 85 | m_LocalPosition: {x: 0, y: 0, z: 0} 86 | m_LocalScale: {x: 1, y: 1, z: 1} 87 | m_Children: [] 88 | m_Father: {fileID: 450926} 89 | m_RootOrder: 0 90 | --- !u!23 &2341492 91 | MeshRenderer: 92 | m_ObjectHideFlags: 1 93 | m_PrefabParentObject: {fileID: 0} 94 | m_PrefabInternal: {fileID: 100100000} 95 | m_GameObject: {fileID: 182930} 96 | m_Enabled: 1 97 | m_CastShadows: 1 98 | m_ReceiveShadows: 1 99 | m_Materials: 100 | - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} 101 | m_SubsetIndices: 102 | m_StaticBatchRoot: {fileID: 0} 103 | m_UseLightProbes: 1 104 | m_ReflectionProbeUsage: 1 105 | m_ProbeAnchor: {fileID: 0} 106 | m_ScaleInLightmap: 1 107 | m_PreserveUVs: 0 108 | m_IgnoreNormalsForChartDetection: 0 109 | m_ImportantGI: 0 110 | m_MinimumChartSize: 4 111 | m_AutoUVMaxDistance: .5 112 | m_AutoUVMaxAngle: 89 113 | m_LightmapParameters: {fileID: 0} 114 | m_SortingLayerID: 0 115 | m_SortingOrder: 0 116 | --- !u!23 &2383948 117 | MeshRenderer: 118 | m_ObjectHideFlags: 1 119 | m_PrefabParentObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 100100000} 121 | m_GameObject: {fileID: 189376} 122 | m_Enabled: 1 123 | m_CastShadows: 1 124 | m_ReceiveShadows: 1 125 | m_Materials: 126 | - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} 127 | m_SubsetIndices: 128 | m_StaticBatchRoot: {fileID: 0} 129 | m_UseLightProbes: 1 130 | m_ReflectionProbeUsage: 1 131 | m_ProbeAnchor: {fileID: 0} 132 | m_ScaleInLightmap: 1 133 | m_PreserveUVs: 0 134 | m_IgnoreNormalsForChartDetection: 0 135 | m_ImportantGI: 0 136 | m_MinimumChartSize: 4 137 | m_AutoUVMaxDistance: .5 138 | m_AutoUVMaxAngle: 89 139 | m_LightmapParameters: {fileID: 0} 140 | m_SortingLayerID: 0 141 | m_SortingOrder: 0 142 | --- !u!102 &10256288 143 | TextMesh: 144 | serializedVersion: 3 145 | m_ObjectHideFlags: 1 146 | m_PrefabParentObject: {fileID: 0} 147 | m_PrefabInternal: {fileID: 100100000} 148 | m_GameObject: {fileID: 182930} 149 | m_Text: Dark Skies 150 | m_OffsetZ: 0 151 | m_CharacterSize: 1 152 | m_LineSpacing: 1 153 | m_Anchor: 4 154 | m_Alignment: 1 155 | m_TabSize: 4 156 | m_FontSize: 120 157 | m_FontStyle: 3 158 | m_RichText: 1 159 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 160 | m_Color: 161 | serializedVersion: 2 162 | rgba: 4294967295 163 | --- !u!102 &10283204 164 | TextMesh: 165 | serializedVersion: 3 166 | m_ObjectHideFlags: 1 167 | m_PrefabParentObject: {fileID: 0} 168 | m_PrefabInternal: {fileID: 100100000} 169 | m_GameObject: {fileID: 189376} 170 | m_Text: Press Space to Start 171 | m_OffsetZ: 0 172 | m_CharacterSize: 1 173 | m_LineSpacing: 1 174 | m_Anchor: 4 175 | m_Alignment: 1 176 | m_TabSize: 4 177 | m_FontSize: 40 178 | m_FontStyle: 0 179 | m_RichText: 1 180 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 181 | m_Color: 182 | serializedVersion: 2 183 | rgba: 4294967295 184 | --- !u!1001 &100100000 185 | Prefab: 186 | m_ObjectHideFlags: 1 187 | serializedVersion: 2 188 | m_Modification: 189 | m_TransformParent: {fileID: 0} 190 | m_Modifications: [] 191 | m_RemovedComponents: [] 192 | m_ParentPrefab: {fileID: 0} 193 | m_RootGameObject: {fileID: 104874} 194 | m_IsPrefabParent: 1 195 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Prefabs/Title.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 20e534b0792bb4f08b0484e334d25fab 3 | timeCreated: 1452465365 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d549bfae05a2543bd9433913f767fc78 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c804828e85cb480693b08e35843e44d 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/Planes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdb7faf752d144a53b6ab7484e0e336b 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/Planes/SmallPlanes.bytes: -------------------------------------------------------------------------------- 1 | Crackerjack: 2 | RotationRate: 90 3 | Speed: 10 4 | HitPoints: 6 5 | 6 | AIRange: 20 7 | 8 | Fuselage: [0, 0] 9 | Wing: 10 | Pos: [0.2, 0] 11 | Size: [1.4, 1] 12 | Stabilizer: [0, -1.2] 13 | GunMounts: 14 | - Name: Piddler 15 | Location: [1, 1.5] 16 | - Name: Piddler 17 | Location: [-1, 1.5] 18 | - Name: Piddler 19 | Location: [2, 1.5] 20 | - Name: Piddler 21 | Location: [-2, 1.5] 22 | 23 | LootTable: 24 | - Weight: 2 25 | Health: 5 26 | - Weight: 1 27 | 28 | 29 | Swoop: 30 | RotationRate: 50 31 | Speed: 20 32 | HitPoints: 4 33 | 34 | AIRange: 30 35 | 36 | Fuselage: 37 | Pos: [0, 0] 38 | Size: [1.4, 1] 39 | Wing: 40 | Pos: [0.2, 0.2] 41 | Size: [0.6, 1] 42 | Stabilizer: [0, -1.2] 43 | GunMounts: 44 | - Name: Long Gun 45 | Location: [0, 3] 46 | 47 | LootTable: 48 | - Weight: 2 49 | Health: 6 50 | - Weight: 2 51 | 52 | 53 | Boomer: 54 | RotationRate: 70 55 | Speed: 6 56 | HitPoints: 20 57 | 58 | AIRange: 20 59 | 60 | Fuselage: 61 | Pos: [0, 0] 62 | Size: [2, 2] 63 | Wing: 64 | Pos: [0.4, 0.2] 65 | Size: [0.6, 2] 66 | Stabilizer: 67 | Pos: [0.2, -2.5] 68 | Size: [1, 1] 69 | GunMounts: 70 | - Name: MG2 71 | Location: [-0.25, 3.5] 72 | - Name: MG2 73 | Location: [0.25, 3.5] 74 | 75 | LootTable: 76 | - Weight: 2 77 | Health: 10 78 | - Weight: 6 79 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/Planes/SmallPlanes.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64f34bd932d7a48df87989f43dbd7eaa 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/Planes/Whip.bytes: -------------------------------------------------------------------------------- 1 | Whip: 2 | RotationRate: 200 3 | Speed: 15 4 | HitPoints: 10 5 | 6 | AIRange: 10 7 | 8 | Fuselage: [0, 0] 9 | Wing: [0.2, -0.2] 10 | Stabilizer: 11 | Pos: [0, -1.2] 12 | Size: [0.9, 0.9] 13 | GunMounts: 14 | - Name: MG1 15 | Location: [0, 2.5] 16 | 17 | LootTable: 18 | - Weight: 1 19 | Health: 5 20 | - Weight: 1 21 | CardName: Whip 22 | - Weight: 5 # drop nothing 23 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/Planes/Whip.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6687ca752e5664b93a4db13255548d84 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/enemy_spawning.bytes: -------------------------------------------------------------------------------- 1 | NumEnemies: 5 2 | SpawnDistanceFromPlayer: 30 -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/enemy_spawning.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 531f54898f56f45e285cdfcdd555936a 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/guns.bytes: -------------------------------------------------------------------------------- 1 | MG1: 2 | BulletSize: [1, 1] 3 | BulletDamage: 2 4 | BulletSpeed: 20 5 | BulletRange: 30 6 | RPS: 6 7 | 8 | MG2: 9 | BulletSize: [1, 1] 10 | BulletDamage: 2 11 | BulletSpeed: 25 12 | BulletRange: 35 13 | RPS: 8 14 | 15 | MG3: 16 | BulletSize: [1, 1] 17 | BulletDamage: 2 18 | BulletSpeed: 30 19 | BulletRange: 40 20 | RPS: 10 21 | 22 | Long Gun: 23 | BulletSize: [2, 1] 24 | BulletDamage: 4 25 | BulletSpeed: 10 26 | BulletRange: 60 27 | RPS: 1 28 | 29 | Piddler: 30 | BulletSize: [0.5, 1] 31 | BulletDamage: 1 32 | BulletSpeed: 18 33 | BulletRange: 40 34 | RPS: 0.1 -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/guns.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5fe4ce5a50524c0ba527d3c1bc08113 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/index.bytes: -------------------------------------------------------------------------------- 1 | # automatically generated DarkConfig index file 2 | # 3 | --- 4 | - enemy_spawning 5 | - guns 6 | - index 7 | - player 8 | - Planes/SmallPlanes 9 | - Planes/Whip 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/index.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 373f8dc58fcb640dfb824976659aa9cf 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/player.bytes: -------------------------------------------------------------------------------- 1 | StartingCard: Whip 2 | Keyboard: 3 | Left: LeftArrow 4 | Right: RightArrow 5 | Boost: UpArrow 6 | Slow: DownArrow 7 | Fire: Space -------------------------------------------------------------------------------- /demo/Assets/Demo/Resources/Configs/player.bytes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 89c7dacda5da649569b2e0bc0960217a 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b87f3c31c0e454cf18bbffd16e7aab3b 3 | folderAsset: yes 4 | timeCreated: 1452659925 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scenes/Loader.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a55d93e2b22ab4e3cbefce36b8389251 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scenes/PlaneDemo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65f06b13702854bbe9b379035e179cf8 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c190061a7c4804e2e991c01d2d5ed8dc 3 | folderAsset: yes 4 | timeCreated: 1452660030 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/AIController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class AIController : MonoBehaviour { 4 | public PlaneController Controller; 5 | public Transform PickupPrefab; 6 | 7 | //////////////////////////////////////////// 8 | 9 | public void Setup(PlaneCard card) { 10 | Controller.Setup(card); 11 | } 12 | 13 | //////////////////////////////////////////// 14 | 15 | void Update() { 16 | // try and target the player (which is a singleton because it's a single player game) 17 | var player = MetaGame.Instance.GetPlayer(); 18 | if (player == null) { 19 | return; 20 | } 21 | var directionToPlayer = player.transform.position - transform.position; 22 | var angleToPlayer = (Mathf.Atan2(directionToPlayer.y, directionToPlayer.x) * Mathf.Rad2Deg - 90) % 360f; 23 | var myAngle = transform.eulerAngles.z % 360f; 24 | 25 | var turnAmount = Mathf.Clamp((angleToPlayer - myAngle) / 45, -1, 1); 26 | 27 | if (Controller == null) { 28 | return; 29 | } 30 | Controller.RotationCommand = turnAmount; 31 | 32 | var playerIsClose = directionToPlayer.magnitude < Controller.Card.AIRange; 33 | Controller.IsFiring = playerIsClose && Mathf.Abs(angleToPlayer - myAngle) < 20; 34 | 35 | Controller.Throttle = 1; 36 | } 37 | 38 | void Killed() { 39 | MetaGame.Instance.AIKilled(); 40 | 41 | // spawn loot from the loot table 42 | var lootTable = Controller.Card.LootTable; 43 | if (lootTable == null) { 44 | Debug.LogError("null lootTable " + Controller.Card); 45 | return; 46 | } 47 | 48 | var totalWeight = 0f; 49 | foreach (var entry in lootTable) { 50 | if (entry == null) { 51 | Debug.Log("entry null"); 52 | continue; 53 | } 54 | 55 | totalWeight += entry.Weight; 56 | } 57 | 58 | var rnd = totalWeight * Random.value; 59 | 60 | foreach (var lootTableEntry in lootTable) { 61 | if (rnd > lootTableEntry.Weight) { 62 | rnd -= lootTableEntry.Weight; 63 | } else { 64 | var loot = lootTableEntry; 65 | if (loot.Health == 0 && loot.CardName == null) return; 66 | 67 | var pickupObj = Instantiate(PickupPrefab, transform.position, Quaternion.identity); 68 | var pickup = pickupObj.GetComponent(); 69 | 70 | pickup.Health = loot.Health; 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/AIController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e746dc99bf5984be5abc08aec0e62d4c 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Bullet.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Bullet : MonoBehaviour { 4 | public int Damage; 5 | public float Speed; 6 | public GameObject HitPrefab; 7 | 8 | [HideInInspector] 9 | public Transform Firer; 10 | 11 | //////////////////////////////////////////// 12 | 13 | void OnTriggerEnter2D(Collider2D c) { 14 | var trf = TopParent(c.transform); 15 | if (trf == Firer) return; 16 | var planeController = trf.GetComponent(); 17 | if (planeController == null) return; 18 | planeController.TakeDamage(Damage); 19 | 20 | var obj = Instantiate(HitPrefab, transform.position, transform.rotation); 21 | obj.transform.localScale = Vector3.one * Mathf.Sqrt(Damage); 22 | Destroy(obj, 2); 23 | Destroy(gameObject); 24 | } 25 | 26 | Transform TopParent(Transform t) { 27 | while (t.parent != null) { 28 | t = t.parent; 29 | } 30 | 31 | return t; 32 | } 33 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Bullet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 75c0ac8114f2e4a4f8f0565b350c5183 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/CameraFollow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class CameraFollow : MonoBehaviour { 4 | public Transform Target; 5 | 6 | public Vector3 RelativePosition = new Vector3(0, 0, -10); 7 | 8 | void LateUpdate() { 9 | if (Target == null) { 10 | return; 11 | } 12 | transform.position = Target.position + RelativePosition; 13 | } 14 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/CameraFollow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 05c24164f4871438fac069bc9648a92e 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da1c6e5fc861c45b1b4e015a721ac209 3 | folderAsset: yes 4 | timeCreated: 1462951262 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Editor/DemoEditorMenus.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using DarkConfig; 3 | 4 | public static class DemoEditorMenus { 5 | [MenuItem("Assets/DarkConfig/Autogenerate Index")] 6 | static void MenuGenerateIndex() { 7 | EditorUtils.GenerateIndex("/Demo/Resources/Configs"); 8 | AssetDatabase.Refresh(); 9 | } 10 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Editor/DemoEditorMenus.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 843a05b79c0254e329c9e8b287e67063 3 | timeCreated: 1462951276 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/EnemySpawner.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using DarkConfig; 4 | 5 | public class EnemySpawner : MonoBehaviour { 6 | public GameObject EnemyPrefab; 7 | 8 | ///////////////////////////////////////////////// 9 | 10 | // Set by config 11 | int numEnemies = 5; 12 | int spawnDistanceFromPlayer = 30; 13 | 14 | // Instance vars 15 | List enemies = new List(); 16 | PlayerController player; 17 | 18 | ///////////////////////////////////////////////// 19 | 20 | void Start() { 21 | // This is _not_ the main initialization code, that's in LoadGame.cs. 22 | // This code runs in the editor, in the PlaneDemo scene, if LoadGame 23 | // hasn't run yet. 24 | // What happens here is that we add the source and then call ApplyThis 25 | // without calling Configs.Preload. In the Unity editor (or as 26 | // determined by the Platform implementation), it will trigger an 27 | // "immediate preload" inside ApplyThis that will load/parse all the 28 | // config files within the function call (so it'll be slow and drop a 29 | // frame). 30 | if (Configs.NumConfigSources == 0) { 31 | Configs.AddConfigSource(new FileSource(Application.dataPath + "/Demo/Resources/Configs", ".bytes")); 32 | } 33 | 34 | Configs.ApplyThis("enemy_spawning", this); 35 | } 36 | 37 | void Update() { 38 | if (player == null) { 39 | player = FindObjectOfType(); 40 | } 41 | 42 | if (player == null) { 43 | return; 44 | } 45 | 46 | // clean out destroyed enemies 47 | for (int i = 0; i < enemies.Count; i++) { 48 | if (enemies[i] == null) { 49 | enemies.RemoveAt(i); 50 | i--; 51 | } 52 | } 53 | 54 | if (enemies.Count < numEnemies) { 55 | // pick a card, any card (except the card the player currently has) 56 | PlaneCard chosenCard = null; 57 | while (chosenCard == null || chosenCard == player.Controller.Card) { 58 | var cardNames = new List(PlaneCard.Cards.Keys); 59 | var chosenName = cardNames[(int) (Random.value * PlaneCard.Cards.Count)]; 60 | chosenCard = PlaneCard.Cards[chosenName]; 61 | } 62 | 63 | // pick a location near the player 64 | var spawnPos = player.transform.position + (Vector3)Random.insideUnitCircle.normalized * spawnDistanceFromPlayer; 65 | var spawnRotation = Quaternion.AngleAxis(Random.value * 360, Vector3.forward); 66 | 67 | // set up the ai 68 | var enemyObj = Instantiate(EnemyPrefab, spawnPos, spawnRotation); 69 | var controller = enemyObj.GetComponent(); 70 | controller.Setup(chosenCard); 71 | 72 | enemies.Add(controller); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/EnemySpawner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 34d9b84e171d2450b8bf84a020c56e1e 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/GunCard.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using DarkConfig; 4 | 5 | /// This is a "config data class", which mostly has public fields and not much else. 6 | public class GunCard { 7 | public Vector2 BulletSize = new Vector2(1, 1); 8 | public int BulletDamage; 9 | public float BulletSpeed; 10 | public float BulletRange; 11 | 12 | public float RPS; 13 | 14 | public float FireInterval => 1f / RPS; 15 | 16 | //////////////////////////////////////////// 17 | 18 | // This static collection allows us to manage the configs for the GunCard 19 | // completely within the GunCard class. Just have to be a little careful 20 | // to not access Cards before the preload finishes. 21 | [ConfigIgnore] 22 | static Dictionary _Cards; 23 | 24 | public static Dictionary Cards { 25 | get { 26 | if (_Cards == null) { 27 | Configs.Apply("guns", ref _Cards); 28 | } 29 | return _Cards; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/GunCard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2aace6748d2d74811804d972224d4300 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/LoadGame.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using UnityEngine; 3 | using DarkConfig; 4 | using System.Diagnostics; 5 | using UnityEngine.SceneManagement; 6 | 7 | // This is the main loading class for the game. It's expected to run inside 8 | // its own scene, which then could display a loading indicator. 9 | public class LoadGame : MonoBehaviour { 10 | Stopwatch stopwatch; 11 | 12 | ///////////////////////////////////////////////// 13 | 14 | void Awake() { 15 | #if DEBUG 16 | // Be strict in debug mode so that content creators will be quickly 17 | // notified of any mistakes. It will warn for any missing fields 18 | // (which haven't been annotated with ConfigAllowMissing) and for any 19 | // extra fields. 20 | Configs.Settings.DefaultReifierOptions = ReificationOptions.None; 21 | #else 22 | // In production mode, ignore missing/extra checks. This makes 23 | // loading faster. ConfigMandatory fields are still checked. 24 | Configs.Settings.DefaultReifierOptions = ConfigOptions.AllowMissingExtraFields; 25 | #endif 26 | 27 | UnityPlatform.Setup(); 28 | Configs.AddConfigSource(new FileSource(Application.dataPath + "/Demo/Resources/Configs", ".bytes", hotload: true)); 29 | StartCoroutine(StartGame()); 30 | } 31 | 32 | IEnumerator StartGame() { 33 | stopwatch = Stopwatch.StartNew(); 34 | 35 | // comment to disable periodic hotloading of files, it'll have to be manual 36 | Configs.Settings.EnableHotloading = true; 37 | 38 | // Preload will call StartGame when it's finished 39 | foreach (object _ in Configs.StepPreload()) { 40 | yield return null; 41 | } 42 | 43 | stopwatch.Stop(); 44 | UnityEngine.Debug.Log("Config parsing ms: " + stopwatch.ElapsedMilliseconds); 45 | 46 | // PlaneCards are loaded on first access so this call to LoadConfigs is 47 | // functionally unnecessary, but since we're taking a framerate hit with 48 | // LoadLevel, might as well make it a tiny bit longer and load the cards 49 | // at the same time 50 | PlaneCard.LoadConfigs(); 51 | SceneManager.LoadScene("PlaneDemo"); 52 | } 53 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/LoadGame.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 922c3748c48304a54a7f4630ec12471c 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Location.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using DarkConfig; 3 | 4 | public class Location { 5 | public Vector2 Pos; 6 | 7 | [ConfigAllowMissing] 8 | public Vector2 Size = new Vector2(1, 1); 9 | 10 | public Location(Vector2 pos, Vector2 size) { 11 | Pos = pos; 12 | Size = size; 13 | } 14 | 15 | // let's take over the parsing of Location, because we want to be able to 16 | // have a short form for the common case of specifying only the position 17 | public static Location FromDoc(Location existing, DocNode doc) { 18 | if (existing == null) { 19 | // want to modify an existing Location if possible, but if it's 20 | // null we need to instantiate it 21 | existing = new Location(default, default); 22 | } 23 | 24 | if (doc.Type == DocNodeType.List) { 25 | // it's a list, so we treat it as a position only, and size is 1,1 26 | Configs.Reify(ref existing.Pos, doc); 27 | existing.Size = new Vector2(1, 1); 28 | } else { 29 | // Do the default parsing for an object. Note that calling 30 | // Config.Reify on the same type would trigger infinite recursion. 31 | Configs.SetFieldsOnObject(ref existing, doc); 32 | } 33 | 34 | return existing; 35 | } 36 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Location.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f90b18ca67c9a433289c14f4db6acdc7 3 | timeCreated: 1487538571 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/MetaGame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using DarkConfig; 4 | 5 | public class MetaGame : MonoBehaviour { 6 | [Header("Prefabs")] 7 | public GameObject PlayerPrefab; 8 | public GameObject TitlePrefab; 9 | 10 | [Header("UI")] 11 | public TextMesh Score; 12 | 13 | [Header("References")] 14 | public GameObject Background; 15 | 16 | // Singleton. 17 | public static MetaGame Instance; 18 | 19 | ///////////////////////////////////////////////// 20 | 21 | public void PlayerKilled() { 22 | SetState(GameState.Postgame); 23 | } 24 | 25 | public void AIKilled() { 26 | score++; 27 | Score.text = string.Format("Score: {0}", score); 28 | } 29 | 30 | public PlayerController GetPlayer() { 31 | if (player == null) return null; 32 | return player; 33 | } 34 | 35 | ///////////////////////////////////////////////// 36 | 37 | enum GameState { 38 | Title, 39 | Playing, 40 | Postgame 41 | } 42 | 43 | int score; 44 | float currentStateStartTime; 45 | Transform title; 46 | PlayerController player; 47 | GameState currentState; 48 | 49 | ///////////////////////////////////////////////// 50 | 51 | void Awake() { 52 | Instance = this; 53 | } 54 | 55 | void Start() { 56 | SetState(GameState.Title); 57 | } 58 | 59 | void Update() { 60 | Configs.Update(Time.deltaTime); 61 | 62 | switch (currentState) { 63 | case GameState.Title: 64 | if (Input.GetKeyDown(KeyCode.Space)) { 65 | SetState(GameState.Playing); 66 | } 67 | break; 68 | case GameState.Playing: 69 | break; 70 | case GameState.Postgame: 71 | if (Time.time - currentStateStartTime > 10 || Input.GetKeyDown(KeyCode.Space)) { 72 | SetState(GameState.Title); 73 | } 74 | break; 75 | default: 76 | throw new ArgumentOutOfRangeException(); 77 | } 78 | 79 | // Shift+H to hotload 80 | if (Input.GetKeyDown(KeyCode.H) && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) { 81 | Debug.Log("Hotloading configs"); 82 | Configs.DoImmediateHotload(); 83 | } 84 | 85 | // Q toggles hotloading 86 | if (Input.GetKeyDown(KeyCode.Q)) { 87 | Configs.Settings.EnableHotloading = !Configs.Settings.EnableHotloading; 88 | Debug.Log("Setting auto hotloading to: " + Configs.Settings.EnableHotloading); 89 | } 90 | } 91 | 92 | void SetState(GameState newState) { 93 | if (currentState != newState) { 94 | ExitState(currentState); 95 | currentState = newState; 96 | currentStateStartTime = Time.time; 97 | } 98 | 99 | switch (newState) { 100 | case GameState.Title: 101 | Camera.main.transform.position = new Vector3(0, 0, -10); 102 | title = Instantiate(TitlePrefab).transform; 103 | break; 104 | case GameState.Playing: 105 | Score.gameObject.SetActive(true); 106 | score = 0; 107 | Score.text = "Score: 0"; 108 | 109 | var playerTrf = Instantiate(PlayerPrefab).transform; 110 | player = playerTrf.GetComponent(); 111 | FindObjectOfType().Target = playerTrf; 112 | 113 | Background.BroadcastMessage("Init", playerTrf); 114 | 115 | break; 116 | case GameState.Postgame: 117 | break; 118 | } 119 | } 120 | 121 | void ExitState(GameState state) { 122 | switch (state) { 123 | case GameState.Title: 124 | Destroy(title.gameObject); 125 | break; 126 | case GameState.Playing: 127 | break; 128 | case GameState.Postgame: 129 | Score.gameObject.SetActive(false); 130 | break; 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/MetaGame.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d90a3fe7400542ffa852129d357882e 3 | timeCreated: 1452464780 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Parallax.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Parallax : MonoBehaviour { 4 | public bool drift; 5 | public Transform ViewpointObject; 6 | 7 | ///////////////////////////////////////////////// 8 | 9 | Vector3 currentPos; 10 | Vector3 startPos; 11 | Vector3 viewpointStartPos; 12 | 13 | ///////////////////////////////////////////////// 14 | 15 | void Awake() { 16 | startPos = transform.position; 17 | currentPos = startPos; 18 | } 19 | 20 | void LateUpdate() { 21 | if (ViewpointObject != null) { 22 | var pos = ViewpointObject.transform.position - viewpointStartPos; 23 | float depth = Mathf.Max(1, transform.position.z); 24 | pos *= 1 - 1 / depth; 25 | var newPos = startPos + pos; 26 | newPos.z = depth; 27 | currentPos = newPos; 28 | } 29 | 30 | if (drift) { 31 | transform.position = currentPos + new Vector3( 32 | Mathf.Sin(Time.time * 0.152f + (name.GetHashCode() & 0xFF)) * 10, 33 | Mathf.Cos(Time.time * 0.1193f + ((name.GetHashCode() & 0xFF00) >> 8)) * 10, 34 | 0); 35 | } else { 36 | transform.position = currentPos; 37 | } 38 | } 39 | 40 | void Init(Transform obj) { 41 | ViewpointObject = obj; 42 | viewpointStartPos = ViewpointObject.position; 43 | } 44 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Parallax.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3b9914a9ae2d943959bd096fc9693f2d 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Pickup.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Pickup : MonoBehaviour { 4 | // these two fields are used if it's a health pickup 5 | public int Health; 6 | public SpriteRenderer PlusSprite; 7 | 8 | //////////////////////////////////////////// 9 | 10 | void Start() { 11 | PlusSprite.color = Color.green; 12 | } 13 | 14 | void OnTriggerEnter2D(Collider2D c) { 15 | var topParent = c.transform; 16 | 17 | while (topParent.parent != null) { 18 | topParent = topParent.parent; 19 | } 20 | 21 | if (!topParent.CompareTag("Player")) { 22 | return; 23 | } 24 | 25 | var planeController = topParent.GetComponent(); 26 | if (planeController != null) { 27 | if (Health > 0) { 28 | planeController.Heal(Health); 29 | } 30 | 31 | Destroy(gameObject); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/Pickup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae9b4960a1fef4f3a9f837a0cca1816c 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneCard.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using DarkConfig; 4 | 5 | public class GunMount { 6 | public string Name; 7 | public Location Location; 8 | 9 | // Note that this is assuming that GunCard.Cards is loaded by the 10 | // time we get into this property accessor. 11 | public GunCard Card => GunCard.Cards[Name]; 12 | } 13 | 14 | public class LootTableEntry { 15 | // Don't permit this field to be missing in the config, even if DarkConfig 16 | // isn't being strict. 17 | [ConfigMandatory] 18 | public float Weight; 19 | 20 | // Permit this field to be missing in the config, even if DarkConfig is 21 | // being strict. 22 | [ConfigAllowMissing] 23 | public int Health; 24 | 25 | [ConfigAllowMissing] 26 | public string CardName; 27 | } 28 | 29 | public class PlaneCard { 30 | // Fields that are expected to be set in configs. 31 | public Location Fuselage = new Location(new Vector2(0, 0), new Vector2(1, 1)); 32 | public Location Wing = new Location(new Vector2(0, 0), new Vector2(1, 1)); 33 | public Location Stabilizer = new Location(new Vector2(0, -1), new Vector2(1, 1)); 34 | 35 | public float RotationRate = 100; 36 | public float Speed = 15; 37 | public int HitPoints = 5; 38 | 39 | public float AIRange = 5; 40 | 41 | public List GunMounts; 42 | 43 | [ConfigMandatory] 44 | public List LootTable; 45 | 46 | ///////////////////////////////////////////////////////// 47 | 48 | // this field can't be set by DarkConfig because it's a function; it's 49 | // also ignored for clarity 50 | [ConfigIgnore] 51 | public System.Action OnChanged; 52 | 53 | // see LoadConfigs for where this is hooked up 54 | [ConfigIgnore] 55 | static Dictionary _Cards; 56 | 57 | // DarkConfig can't currently set properties 58 | public static Dictionary Cards { 59 | get { 60 | if (_Cards == null) { 61 | LoadConfigs(); 62 | } 63 | return _Cards; 64 | } 65 | } 66 | 67 | public static void LoadConfigs() { 68 | // loads all config files in the Planes directory 69 | Configs.ParseFilesAsMergedDict("Planes/**", doc => { 70 | Configs.Reify(ref _Cards, doc); 71 | return true; 72 | }); 73 | } 74 | 75 | // We have a few places in the code which need to be notified when their 76 | // PlaneCard is modified. These are places where we had no choice but to 77 | // copy some of the values from the PlaneCard into some other object, and 78 | // therefore need to re-copy the values when the PlaneCard gets hotloaded. 79 | // 80 | // To see those use cases, look for usage of OnChanged in PlaneView.cs. 81 | // See hotloading.md for more information on hotloading in general. 82 | public static PlaneCard PostDoc(PlaneCard existing) { 83 | existing.OnChanged?.Invoke(existing); 84 | return existing; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneCard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1f1dd201afcfb40bcbc6ab907018bacf 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | public class PlaneController : MonoBehaviour { 5 | public float RotationCommand; 6 | public bool IsFiring; 7 | public float Throttle = 1; 8 | 9 | public int HitPoints; 10 | 11 | // note that this is a property rather than a field, so that hotloaded 12 | // changes to the card will affect the MaxHitPoints implicitly 13 | public int MaxHitPoints { 14 | get { 15 | if (Card == null) { 16 | return 1; 17 | } 18 | if (CompareTag("Player")) { 19 | // for gameplay reasons, players are more durable 20 | return Card.HitPoints * 2; 21 | } 22 | 23 | return Card.HitPoints; 24 | } 25 | } 26 | 27 | public PlaneCard Card; 28 | 29 | public Transform BulletPrefab; 30 | public Transform ViewPrefab; 31 | 32 | public GameObject ExplosionPrefab; 33 | public GameObject ShotFireFXPrefab; 34 | 35 | [HideInInspector] 36 | public PlaneView View; 37 | 38 | //////////////////////////////////////////// 39 | 40 | public void Setup(PlaneCard card) { 41 | var viewTrf = Instantiate(ViewPrefab, transform.position, transform.rotation); 42 | viewTrf.parent = transform; 43 | View = viewTrf.GetComponent(); 44 | View.Controller = this; 45 | 46 | // here we take a reference to the card; the card object will get 47 | // updated automatically for us if the config hotloads, so we don't 48 | // have to have special hotloading logic in this class 49 | Card = card; 50 | 51 | // do this after assigning to Card b/c MaxHitPoints depends on Card 52 | HitPoints = MaxHitPoints; 53 | lastFiredTimes.Clear(); 54 | 55 | // display the view; this has to be after HitPoints is assigned 56 | // or the view will show the wrong thing 57 | View.Card = card; 58 | } 59 | 60 | public void Heal(int points) { 61 | HitPoints += points; 62 | if (HitPoints > MaxHitPoints) HitPoints = MaxHitPoints; 63 | View.Refresh(Card); 64 | } 65 | 66 | public void TakeDamage(int points) { 67 | HitPoints -= points; 68 | View.Refresh(Card); 69 | if (HitPoints <= 0) { 70 | gameObject.BroadcastMessage("Killed"); 71 | Destroy(gameObject); 72 | var explosion = Instantiate(ExplosionPrefab, transform.position, Quaternion.identity); 73 | Destroy(explosion, 1f); 74 | } 75 | } 76 | 77 | //////////////////////////////////////////// 78 | 79 | // this handles the rate-of-fire for the guns 80 | readonly Dictionary lastFiredTimes = new Dictionary(); 81 | 82 | //////////////////////////////////////////// 83 | 84 | void FixedUpdate() { 85 | var eulers = transform.eulerAngles; 86 | eulers.z += RotationCommand * Card.RotationRate * Time.fixedDeltaTime; 87 | transform.eulerAngles = eulers; 88 | 89 | transform.position += transform.up * Card.Speed * Throttle * Time.fixedDeltaTime; 90 | 91 | var now = Time.fixedTime; 92 | if (IsFiring) { 93 | foreach (var mount in Card.GunMounts) { 94 | if (lastFiredTimes.ContainsKey(mount) && now - lastFiredTimes[mount] < mount.Card.FireInterval) { 95 | continue; 96 | } 97 | 98 | // When we construct a bullet, we copy all its attributes 99 | // from the configs; this means that hotloading won't affect 100 | // existing bullets. That's probably OK; bullets are very 101 | // ephemeral and it's quick to get more of them, so there isn't 102 | // much of a time cost to not hotloading them individually. 103 | // We do very much want hotloading to apply when they're being 104 | // shot, though, otherwise we'd have to restart the entire game 105 | // to see changes, which would be slow. 106 | var gunCard = mount.Card; 107 | var bulletTrf = Instantiate(BulletPrefab, transform.TransformPoint(mount.Location.Pos), transform.rotation); 108 | var bulletComponent = bulletTrf.GetComponent(); 109 | bulletComponent.Damage = gunCard.BulletDamage; 110 | bulletComponent.Speed = Card.Speed * Throttle + gunCard.BulletSpeed; 111 | bulletTrf.GetComponent().velocity = bulletTrf.up * bulletComponent.Speed; 112 | bulletComponent.Firer = transform; 113 | bulletTrf.localScale = new Vector3(gunCard.BulletSize.x, gunCard.BulletSize.y, 1); 114 | 115 | float timeToFly = gunCard.BulletRange / bulletComponent.Speed; 116 | 117 | Destroy(bulletTrf.gameObject, timeToFly); 118 | 119 | lastFiredTimes[mount] = now; 120 | 121 | // display muzzle flash 122 | var fx = Instantiate(ShotFireFXPrefab, transform.TransformPoint(mount.Location.Pos), transform.rotation); 123 | Destroy(fx, 0.5f); 124 | } 125 | } 126 | } 127 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d792d93ca589c474196eb88a2f1ad3fd 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneView.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | [ExecuteInEditMode] 4 | public class PlaneView : MonoBehaviour { 5 | public SpriteRenderer Fuselage; 6 | public SpriteRenderer LeftWing; 7 | public SpriteRenderer RightWing; 8 | public SpriteRenderer LeftStabilizer; 9 | public SpriteRenderer RightStabilizer; 10 | 11 | public PlaneController Controller; 12 | 13 | public PlaneCard Card { 14 | get => _Card; 15 | set { 16 | // we hook up listeners to OnChanged so it gets called when the Card gets modified 17 | if (_Card != null) { 18 | _Card.OnChanged -= Refresh; 19 | } 20 | _Card = value; 21 | _Card.OnChanged += Refresh; 22 | Refresh(_Card); 23 | } 24 | } 25 | 26 | public void Refresh(PlaneCard card) { 27 | // Here, we're copying values from the card because we have to to interface with Unity. 28 | // However, we've arranged things so that this function gets called any time 29 | // the card gets modified. 30 | Fuselage.transform.localPosition = Card.Fuselage.Pos; 31 | Fuselage.transform.localScale = new Vector3(Card.Fuselage.Size.x, Card.Fuselage.Size.y, 1); 32 | LeftWing.transform.localPosition = new Vector2(-Card.Wing.Pos.x, Card.Wing.Pos.y); 33 | LeftWing.transform.localScale = new Vector3(Card.Wing.Size.x, Card.Wing.Size.y, 1); 34 | RightWing.transform.localPosition = Card.Wing.Pos; 35 | RightWing.transform.localScale = new Vector3(-Card.Wing.Size.x, Card.Wing.Size.y, 1); 36 | LeftStabilizer.transform.localPosition = new Vector2(-Card.Stabilizer.Pos.x, Card.Stabilizer.Pos.y); 37 | LeftStabilizer.transform.localScale = Card.Stabilizer.Size; 38 | RightStabilizer.transform.localPosition = Card.Stabilizer.Pos; 39 | RightStabilizer.transform.localScale = new Vector3(-Card.Stabilizer.Size.x, Card.Stabilizer.Size.y, 1); 40 | 41 | if (Controller == null) return; 42 | var healthPct = ((float) Controller.HitPoints) / Controller.MaxHitPoints; 43 | var color = Color.Lerp(Color.white, Color.Lerp(Color.red, Color.black, 0.2f), 1 - healthPct); 44 | Fuselage.color = color; 45 | LeftWing.color = color; 46 | RightWing.color = color; 47 | LeftStabilizer.color = color; 48 | RightStabilizer.color = color; 49 | } 50 | 51 | //////////////////////////////////////////// 52 | 53 | PlaneCard _Card; 54 | 55 | //////////////////////////////////////////// 56 | 57 | void OnDestroy() { 58 | // need to clean up this listener so it's not a memory leak 59 | if (Card != null) { 60 | Card.OnChanged -= Refresh; 61 | } 62 | } 63 | 64 | void Killed() { } 65 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlaneView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e44d58f6a31b44603b3c1ffbd9674cc6 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlayerController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using DarkConfig; 4 | 5 | public class PlayerController : MonoBehaviour { 6 | public static string StartingCard = null; 7 | 8 | public Dictionary Keyboard; 9 | 10 | [ConfigIgnore] 11 | public PlaneController Controller; 12 | 13 | //////////////////////////////////////////// 14 | 15 | void Start() { 16 | // TODO (graham): temp fix for demo. 17 | var reifierOptions = Configs.Settings.DefaultReifierOptions; 18 | Configs.Settings.DefaultReifierOptions = reifierOptions | ReificationOptions.AllowExtraFields; 19 | 20 | // Get keyboard bindings from the config, and also automatically 21 | // hotload them. 22 | Configs.ApplyThis("player", this); 23 | // The previous call to ApplyThis won't have touched the StartingCard 24 | // field, so for that we call ApplyStatic. 25 | Configs.ApplyStatic("player"); 26 | 27 | Configs.Settings.DefaultReifierOptions = reifierOptions; 28 | 29 | Controller.Setup(PlaneCard.Cards[StartingCard]); 30 | } 31 | 32 | void Update() { 33 | float rotation = 0; 34 | if (Input.GetKey(Keyboard["Left"])) { 35 | rotation += 1; 36 | } 37 | 38 | if (Input.GetKey(Keyboard["Right"])) { 39 | rotation -= 1; 40 | } 41 | 42 | if (Input.GetKey(Keyboard["Slow"])) { 43 | Controller.Throttle = 0.6f; 44 | } 45 | 46 | if (Input.GetKey(Keyboard["Boost"])) { 47 | Controller.Throttle = 1.4f; 48 | } 49 | 50 | Controller.RotationCommand = rotation; 51 | 52 | Controller.IsFiring = Input.GetKey(Keyboard["Fire"]); 53 | } 54 | 55 | void Killed() { 56 | MetaGame.Instance.PlayerKilled(); 57 | } 58 | } -------------------------------------------------------------------------------- /demo/Assets/Demo/Scripts/PlayerController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 74880b4d8c9c547a59e921a550dbe9ea 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /demo/Assets/Demo/generate_random_configs.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import random 4 | 5 | num_configs = int(sys.argv[1]) 6 | start_value = int(sys.argv[2]) 7 | 8 | class ArtPos(object): 9 | def __init__(self, pos, size): 10 | self.Pos = pos 11 | self.Size = size 12 | 13 | def __str__(self): 14 | return "\n Pos: [%f, %f]\n Size: [%f, %f]\n" % ( 15 | self.Pos[0], self.Pos[1], self.Size[0], self.Size[1]) 16 | 17 | for i in xrange(num_configs): 18 | body = dict() 19 | body["RotationRate"] = random.randint(40, 70) 20 | body["Speed"] = random.randint(5, 20) 21 | body["HitPoints"] = random.randint(3, 7) 22 | body["AIRange"] = 30 23 | body["Fuselage"] = ArtPos([0, 0], [random.uniform(0.8, 1.5), random.uniform(1, 2)]) 24 | body["Wing"] = ArtPos([(body["Fuselage"].Size[0] - 0.8) * 0.5, random.uniform(-0.5, 0.7)], 25 | [random.uniform(0.4, 1.5), random.uniform(0.6, 2)]) 26 | body["Stabilizer"] = ArtPos([0, -body["Fuselage"].Size[1] * random.uniform(0.3, 1)], 27 | [random.uniform(0.5, 2), random.uniform(0.5, 2)]) 28 | body["GunMounts"] = "[{Name: Piddler, Location: [0, 0]}]" 29 | body["LootTable"] = "[{Weight: 2}, {Weight: 1, Health: 2}]" 30 | 31 | print "Generated%s:" % (i + start_value) 32 | for k, v in body.iteritems(): 33 | print " %s: %s" % (k, v) -------------------------------------------------------------------------------- /demo/Assets/Demo/generate_random_configs.py.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 822521391086c444ea914bc603be5bb7 3 | timeCreated: 1453367792 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c0bb187dcde8a0488bb192dffc2a1d7 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Editor/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 46950cd94de97e94cafd75184c515ea2 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/Editor/Tests/UnitySpecificTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1f758bbe1fd24432800783013864594c 3 | timeCreated: 1639167736 -------------------------------------------------------------------------------- /demo/Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ab8149a2d2694eabb19a91f88f48302 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ai.navigation": "1.1.5", 4 | "com.unity.ide.rider": "3.0.31", 5 | "com.unity.ide.visualstudio": "2.0.22", 6 | "com.unity.ide.vscode": "1.2.5", 7 | "com.unity.test-framework": "1.1.33", 8 | "com.unity.ugui": "1.0.0", 9 | "com.unity.modules.ai": "1.0.0", 10 | "com.unity.modules.androidjni": "1.0.0", 11 | "com.unity.modules.animation": "1.0.0", 12 | "com.unity.modules.assetbundle": "1.0.0", 13 | "com.unity.modules.audio": "1.0.0", 14 | "com.unity.modules.cloth": "1.0.0", 15 | "com.unity.modules.director": "1.0.0", 16 | "com.unity.modules.imageconversion": "1.0.0", 17 | "com.unity.modules.imgui": "1.0.0", 18 | "com.unity.modules.jsonserialize": "1.0.0", 19 | "com.unity.modules.particlesystem": "1.0.0", 20 | "com.unity.modules.physics": "1.0.0", 21 | "com.unity.modules.physics2d": "1.0.0", 22 | "com.unity.modules.screencapture": "1.0.0", 23 | "com.unity.modules.terrain": "1.0.0", 24 | "com.unity.modules.terrainphysics": "1.0.0", 25 | "com.unity.modules.tilemap": "1.0.0", 26 | "com.unity.modules.ui": "1.0.0", 27 | "com.unity.modules.uielements": "1.0.0", 28 | "com.unity.modules.umbra": "1.0.0", 29 | "com.unity.modules.unityanalytics": "1.0.0", 30 | "com.unity.modules.unitywebrequest": "1.0.0", 31 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 32 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 33 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 34 | "com.unity.modules.unitywebrequestwww": "1.0.0", 35 | "com.unity.modules.vehicles": "1.0.0", 36 | "com.unity.modules.video": "1.0.0", 37 | "com.unity.modules.vr": "1.0.0", 38 | "com.unity.modules.wind": "1.0.0", 39 | "com.unity.modules.xr": "1.0.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | m_SpeedOfSound: 347 9 | Doppler Factor: 1 10 | Default Speaker Mode: 2 11 | m_DSPBufferSize: 0 12 | m_DisableAudio: 0 13 | -------------------------------------------------------------------------------- /demo/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /demo/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | m_Gravity: {x: 0, y: -9.81000042, z: 0} 7 | m_DefaultMaterial: {fileID: 0} 8 | m_BounceThreshold: 2 9 | m_SleepVelocity: .150000006 10 | m_SleepAngularVelocity: .140000001 11 | m_MaxAngularVelocity: 7 12 | m_MinPenetrationForPenalty: .00999999978 13 | m_SolverIterationCount: 6 14 | m_RaycastsHitTriggers: 1 15 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 16 | -------------------------------------------------------------------------------- /demo/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Demo/Scenes/Loader.unity 10 | - enabled: 1 11 | path: Assets/Demo/Scenes/PlaneDemo.unity 12 | -------------------------------------------------------------------------------- /demo/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 9 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 1 10 | m_DefaultBehaviorMode: 1 11 | m_PrefabRegularEnvironment: {fileID: 0} 12 | m_PrefabUIEnvironment: {fileID: 0} 13 | m_SpritePackerMode: 0 14 | m_SpritePackerPaddingPower: 1 15 | m_EtcTextureCompressorBehavior: 0 16 | m_EtcTextureFastCompressor: 2 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 5 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp;asmref 20 | m_ProjectGenerationRootNamespace: 21 | m_CollabEditorSettings: 22 | inProgressEnabled: 1 23 | m_EnableTextureStreamingInEditMode: 1 24 | m_EnableTextureStreamingInPlayMode: 1 25 | m_AsyncShaderCompilation: 1 26 | m_EnterPlayModeOptionsEnabled: 0 27 | m_EnterPlayModeOptions: 3 28 | m_ShowLightmapResolutionOverlay: 1 29 | m_UseLegacyProbeSampleCount: 1 30 | m_AssetPipelineMode: 1 31 | m_CacheServerMode: 0 32 | m_CacheServerEndpoint: 33 | m_CacheServerNamespacePrefix: default 34 | m_CacheServerEnableDownload: 1 35 | m_CacheServerEnableUpload: 1 36 | -------------------------------------------------------------------------------- /demo/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10782, guid: 0000000000000000f000000000000000, type: 0} 38 | m_PreloadedShaders: [] 39 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 40 | type: 0} 41 | m_ShaderSettings_Tier1: 42 | useCascadedShadowMaps: 1 43 | standardShaderQuality: 2 44 | useReflectionProbeBoxProjection: 1 45 | useReflectionProbeBlending: 1 46 | m_ShaderSettings_Tier2: 47 | useCascadedShadowMaps: 1 48 | standardShaderQuality: 2 49 | useReflectionProbeBoxProjection: 1 50 | useReflectionProbeBlending: 1 51 | m_ShaderSettings_Tier3: 52 | useCascadedShadowMaps: 1 53 | standardShaderQuality: 2 54 | useReflectionProbeBoxProjection: 1 55 | useReflectionProbeBlending: 1 56 | m_BuildTargetShaderSettings: [] 57 | m_LightmapStripping: 0 58 | m_FogStripping: 0 59 | m_LightmapKeepPlain: 1 60 | m_LightmapKeepDirCombined: 1 61 | m_LightmapKeepDirSeparate: 1 62 | m_LightmapKeepDynamicPlain: 1 63 | m_LightmapKeepDynamicDirCombined: 1 64 | m_LightmapKeepDynamicDirSeparate: 1 65 | m_FogKeepLinear: 1 66 | m_FogKeepExp: 1 67 | m_FogKeepExp2: 1 68 | -------------------------------------------------------------------------------- /demo/ProjectSettings/MemorySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!387306366 &1 4 | MemorySettings: 5 | m_ObjectHideFlags: 0 6 | m_EditorMemorySettings: 7 | m_MainAllocatorBlockSize: -1 8 | m_ThreadAllocatorBlockSize: -1 9 | m_MainGfxBlockSize: -1 10 | m_ThreadGfxBlockSize: -1 11 | m_CacheBlockSize: -1 12 | m_TypetreeBlockSize: -1 13 | m_ProfilerBlockSize: -1 14 | m_ProfilerEditorBlockSize: -1 15 | m_BucketAllocatorGranularity: -1 16 | m_BucketAllocatorBucketsCount: -1 17 | m_BucketAllocatorBlockSize: -1 18 | m_BucketAllocatorBlockCount: -1 19 | m_ProfilerBucketAllocatorGranularity: -1 20 | m_ProfilerBucketAllocatorBucketsCount: -1 21 | m_ProfilerBucketAllocatorBlockSize: -1 22 | m_ProfilerBucketAllocatorBlockCount: -1 23 | m_TempAllocatorSizeMain: -1 24 | m_JobTempAllocatorBlockSize: -1 25 | m_BackgroundJobTempAllocatorBlockSize: -1 26 | m_JobTempAllocatorReducedBlockSize: -1 27 | m_TempAllocatorSizeGIBakingWorker: -1 28 | m_TempAllocatorSizeNavMeshWorker: -1 29 | m_TempAllocatorSizeAudioWorker: -1 30 | m_TempAllocatorSizeCloudWorker: -1 31 | m_TempAllocatorSizeGfx: -1 32 | m_TempAllocatorSizeJobWorker: -1 33 | m_TempAllocatorSizeBackgroundWorker: -1 34 | m_TempAllocatorSizePreloadManager: -1 35 | m_PlatformMemorySettings: {} 36 | -------------------------------------------------------------------------------- /demo/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshLayers: 5 | m_ObjectHideFlags: 0 6 | Built-in Layer 0: 7 | name: Default 8 | cost: 1 9 | editType: 2 10 | Built-in Layer 1: 11 | name: Not Walkable 12 | cost: 1 13 | editType: 0 14 | Built-in Layer 2: 15 | name: Jump 16 | cost: 2 17 | editType: 2 18 | User Layer 0: 19 | name: 20 | cost: 1 21 | editType: 3 22 | User Layer 1: 23 | name: 24 | cost: 1 25 | editType: 3 26 | User Layer 2: 27 | name: 28 | cost: 1 29 | editType: 3 30 | User Layer 3: 31 | name: 32 | cost: 1 33 | editType: 3 34 | User Layer 4: 35 | name: 36 | cost: 1 37 | editType: 3 38 | User Layer 5: 39 | name: 40 | cost: 1 41 | editType: 3 42 | User Layer 6: 43 | name: 44 | cost: 1 45 | editType: 3 46 | User Layer 7: 47 | name: 48 | cost: 1 49 | editType: 3 50 | User Layer 8: 51 | name: 52 | cost: 1 53 | editType: 3 54 | User Layer 9: 55 | name: 56 | cost: 1 57 | editType: 3 58 | User Layer 10: 59 | name: 60 | cost: 1 61 | editType: 3 62 | User Layer 11: 63 | name: 64 | cost: 1 65 | editType: 3 66 | User Layer 12: 67 | name: 68 | cost: 1 69 | editType: 3 70 | User Layer 13: 71 | name: 72 | cost: 1 73 | editType: 3 74 | User Layer 14: 75 | name: 76 | cost: 1 77 | editType: 3 78 | User Layer 15: 79 | name: 80 | cost: 1 81 | editType: 3 82 | User Layer 16: 83 | name: 84 | cost: 1 85 | editType: 3 86 | User Layer 17: 87 | name: 88 | cost: 1 89 | editType: 3 90 | User Layer 18: 91 | name: 92 | cost: 1 93 | editType: 3 94 | User Layer 19: 95 | name: 96 | cost: 1 97 | editType: 3 98 | User Layer 20: 99 | name: 100 | cost: 1 101 | editType: 3 102 | User Layer 21: 103 | name: 104 | cost: 1 105 | editType: 3 106 | User Layer 22: 107 | name: 108 | cost: 1 109 | editType: 3 110 | User Layer 23: 111 | name: 112 | cost: 1 113 | editType: 3 114 | User Layer 24: 115 | name: 116 | cost: 1 117 | editType: 3 118 | User Layer 25: 119 | name: 120 | cost: 1 121 | editType: 3 122 | User Layer 26: 123 | name: 124 | cost: 1 125 | editType: 3 126 | User Layer 27: 127 | name: 128 | cost: 1 129 | editType: 3 130 | User Layer 28: 131 | name: 132 | cost: 1 133 | editType: 3 134 | -------------------------------------------------------------------------------- /demo/ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshLayers: 5 | m_ObjectHideFlags: 0 6 | Built-in Layer 0: 7 | name: Default 8 | cost: 1 9 | editType: 2 10 | Built-in Layer 1: 11 | name: Not Walkable 12 | cost: 1 13 | editType: 0 14 | Built-in Layer 2: 15 | name: Jump 16 | cost: 2 17 | editType: 2 18 | User Layer 0: 19 | name: 20 | cost: 1 21 | editType: 3 22 | User Layer 1: 23 | name: 24 | cost: 1 25 | editType: 3 26 | User Layer 2: 27 | name: 28 | cost: 1 29 | editType: 3 30 | User Layer 3: 31 | name: 32 | cost: 1 33 | editType: 3 34 | User Layer 4: 35 | name: 36 | cost: 1 37 | editType: 3 38 | User Layer 5: 39 | name: 40 | cost: 1 41 | editType: 3 42 | User Layer 6: 43 | name: 44 | cost: 1 45 | editType: 3 46 | User Layer 7: 47 | name: 48 | cost: 1 49 | editType: 3 50 | User Layer 8: 51 | name: 52 | cost: 1 53 | editType: 3 54 | User Layer 9: 55 | name: 56 | cost: 1 57 | editType: 3 58 | User Layer 10: 59 | name: 60 | cost: 1 61 | editType: 3 62 | User Layer 11: 63 | name: 64 | cost: 1 65 | editType: 3 66 | User Layer 12: 67 | name: 68 | cost: 1 69 | editType: 3 70 | User Layer 13: 71 | name: 72 | cost: 1 73 | editType: 3 74 | User Layer 14: 75 | name: 76 | cost: 1 77 | editType: 3 78 | User Layer 15: 79 | name: 80 | cost: 1 81 | editType: 3 82 | User Layer 16: 83 | name: 84 | cost: 1 85 | editType: 3 86 | User Layer 17: 87 | name: 88 | cost: 1 89 | editType: 3 90 | User Layer 18: 91 | name: 92 | cost: 1 93 | editType: 3 94 | User Layer 19: 95 | name: 96 | cost: 1 97 | editType: 3 98 | User Layer 20: 99 | name: 100 | cost: 1 101 | editType: 3 102 | User Layer 21: 103 | name: 104 | cost: 1 105 | editType: 3 106 | User Layer 22: 107 | name: 108 | cost: 1 109 | editType: 3 110 | User Layer 23: 111 | name: 112 | cost: 1 113 | editType: 3 114 | User Layer 24: 115 | name: 116 | cost: 1 117 | editType: 3 118 | User Layer 25: 119 | name: 120 | cost: 1 121 | editType: 3 122 | User Layer 26: 123 | name: 124 | cost: 1 125 | editType: 3 126 | User Layer 27: 127 | name: 128 | cost: 1 129 | editType: 3 130 | User Layer 28: 131 | name: 132 | cost: 1 133 | editType: 3 134 | -------------------------------------------------------------------------------- /demo/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /demo/ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 53 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_EnablePreReleasePackages: 0 16 | m_AdvancedSettingsExpanded: 1 17 | m_ScopedRegistriesSettingsExpanded: 1 18 | m_SeeAllPackageVersions: 0 19 | m_DismissPreviewPackagesInUse: 0 20 | oneTimeWarningShown: 0 21 | m_Registries: 22 | - m_Id: main 23 | m_Name: 24 | m_Url: https://packages.unity.com 25 | m_Scopes: [] 26 | m_IsDefault: 1 27 | m_Capabilities: 7 28 | m_ConfigSource: 0 29 | m_UserSelectedRegistryName: 30 | m_UserAddingNewScopedRegistry: 0 31 | m_RegistryInfoDraft: 32 | m_Modified: 0 33 | m_ErrorMessage: 34 | m_UserModificationsInstanceId: -846 35 | m_OriginalInstanceId: -848 36 | m_LoadAssets: 0 37 | -------------------------------------------------------------------------------- /demo/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | m_Gravity: {x: 0, y: -9.81000042} 7 | m_DefaultMaterial: {fileID: 0} 8 | m_VelocityIterations: 8 9 | m_PositionIterations: 3 10 | m_RaycastsHitTriggers: 1 11 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 12 | -------------------------------------------------------------------------------- /demo/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_DefaultPresets: {} 8 | -------------------------------------------------------------------------------- /demo/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2022.3.40f1 2 | m_EditorVersionWithRevision: 2022.3.40f1 (cbdda657d2f0) 3 | -------------------------------------------------------------------------------- /demo/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 3 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Fastest 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | blendWeights: 1 18 | textureQuality: 1 19 | anisotropicTextures: 0 20 | antiAliasing: 0 21 | softParticles: 0 22 | softVegetation: 0 23 | vSyncCount: 0 24 | lodBias: .300000012 25 | maximumLODLevel: 0 26 | particleRaycastBudget: 4 27 | excludedTargetPlatforms: [] 28 | - serializedVersion: 2 29 | name: Fast 30 | pixelLightCount: 0 31 | shadows: 0 32 | shadowResolution: 0 33 | shadowProjection: 1 34 | shadowCascades: 1 35 | shadowDistance: 20 36 | blendWeights: 2 37 | textureQuality: 0 38 | anisotropicTextures: 0 39 | antiAliasing: 0 40 | softParticles: 0 41 | softVegetation: 0 42 | vSyncCount: 0 43 | lodBias: .400000006 44 | maximumLODLevel: 0 45 | particleRaycastBudget: 16 46 | excludedTargetPlatforms: [] 47 | - serializedVersion: 2 48 | name: Simple 49 | pixelLightCount: 1 50 | shadows: 1 51 | shadowResolution: 0 52 | shadowProjection: 1 53 | shadowCascades: 1 54 | shadowDistance: 20 55 | blendWeights: 2 56 | textureQuality: 0 57 | anisotropicTextures: 1 58 | antiAliasing: 0 59 | softParticles: 0 60 | softVegetation: 0 61 | vSyncCount: 0 62 | lodBias: .699999988 63 | maximumLODLevel: 0 64 | particleRaycastBudget: 64 65 | excludedTargetPlatforms: [] 66 | - serializedVersion: 2 67 | name: Good 68 | pixelLightCount: 2 69 | shadows: 2 70 | shadowResolution: 1 71 | shadowProjection: 1 72 | shadowCascades: 2 73 | shadowDistance: 40 74 | blendWeights: 2 75 | textureQuality: 0 76 | anisotropicTextures: 1 77 | antiAliasing: 0 78 | softParticles: 0 79 | softVegetation: 1 80 | vSyncCount: 1 81 | lodBias: 1 82 | maximumLODLevel: 0 83 | particleRaycastBudget: 256 84 | excludedTargetPlatforms: [] 85 | - serializedVersion: 2 86 | name: Beautiful 87 | pixelLightCount: 3 88 | shadows: 2 89 | shadowResolution: 2 90 | shadowProjection: 1 91 | shadowCascades: 2 92 | shadowDistance: 70 93 | blendWeights: 4 94 | textureQuality: 0 95 | anisotropicTextures: 2 96 | antiAliasing: 2 97 | softParticles: 1 98 | softVegetation: 1 99 | vSyncCount: 1 100 | lodBias: 1.5 101 | maximumLODLevel: 0 102 | particleRaycastBudget: 1024 103 | excludedTargetPlatforms: [] 104 | - serializedVersion: 2 105 | name: Fantastic 106 | pixelLightCount: 4 107 | shadows: 2 108 | shadowResolution: 2 109 | shadowProjection: 1 110 | shadowCascades: 4 111 | shadowDistance: 150 112 | blendWeights: 4 113 | textureQuality: 0 114 | anisotropicTextures: 2 115 | antiAliasing: 2 116 | softParticles: 1 117 | softVegetation: 1 118 | vSyncCount: 1 119 | lodBias: 2 120 | maximumLODLevel: 0 121 | particleRaycastBudget: 4096 122 | excludedTargetPlatforms: [] 123 | m_PerPlatformDefaultQuality: {} 124 | -------------------------------------------------------------------------------- /demo/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | tags: 6 | - 7 | Builtin Layer 0: Default 8 | Builtin Layer 1: TransparentFX 9 | Builtin Layer 2: Ignore Raycast 10 | Builtin Layer 3: 11 | Builtin Layer 4: Water 12 | Builtin Layer 5: UI 13 | Builtin Layer 6: 14 | Builtin Layer 7: 15 | User Layer 8: 16 | User Layer 9: 17 | User Layer 10: 18 | User Layer 11: 19 | User Layer 12: 20 | User Layer 13: 21 | User Layer 14: 22 | User Layer 15: 23 | User Layer 16: 24 | User Layer 17: 25 | User Layer 18: 26 | User Layer 19: 27 | User Layer 20: 28 | User Layer 21: 29 | User Layer 22: 30 | User Layer 23: 31 | User Layer 24: 32 | User Layer 25: 33 | User Layer 26: 34 | User Layer 27: 35 | User Layer 28: 36 | User Layer 29: 37 | User Layer 30: 38 | User Layer 31: 39 | m_SortingLayers: 40 | - name: Default 41 | userID: 0 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /demo/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: .0199999996 7 | Maximum Allowed Timestep: .333333343 8 | m_TimeScale: 1 9 | -------------------------------------------------------------------------------- /demo/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_TestInitMode: 0 13 | CrashReportingSettings: 14 | m_EventUrl: https://perf-events.cloud.unity3d.com 15 | m_Enabled: 0 16 | m_LogBufferSize: 10 17 | m_CaptureEditorExceptions: 1 18 | UnityPurchasingSettings: 19 | m_Enabled: 0 20 | m_TestMode: 0 21 | UnityAnalyticsSettings: 22 | m_Enabled: 0 23 | m_TestMode: 0 24 | m_InitializeOnStartup: 1 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /demo/ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_StripUpdateShader: {fileID: 0} 10 | m_RenderPipeSettingsPath: 11 | m_FixedTimeStep: 0.016666668 12 | m_MaxDeltaTime: 0.05 13 | -------------------------------------------------------------------------------- /demo/ProjectSettings/VersionControlSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!890905787 &1 4 | VersionControlSettings: 5 | m_ObjectHideFlags: 0 6 | m_Mode: Visible Meta Files 7 | m_CollabEditorSettings: 8 | inProgressEnabled: 1 9 | -------------------------------------------------------------------------------- /demo/ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/DarkConfig/Attributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DarkConfig { 4 | /// If the field annotated with a Mandatory, or any field on a Mandatory class, 5 | /// is not present in the YAML, DarkConfig will complain, regardless of other 6 | /// settings. 7 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct)] 8 | public class ConfigMandatoryAttribute : Attribute { } 9 | 10 | /// If an AllowMissing field, or any field on an AllowMissing class, is not 11 | /// present in the YAML, DarkConfig will not complain, regardless of other 12 | /// settings. 13 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct)] 14 | public class ConfigAllowMissingAttribute : Attribute { } 15 | 16 | /// If a field has the Ignore attribute, it will be completely ignored by 17 | /// DarkConfig; not set, not checked, it's as if it wasn't on the class in the 18 | /// first place. 19 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 20 | public class ConfigIgnoreAttribute : Attribute { } 21 | 22 | /// If a field has the SourceInformation attribute then the field is 23 | /// automatically populated with DocNode.SourceInformation by SetFieldsOnObject() 24 | /// Useful if you do validation or want better error reporting after reification 25 | /// Use #if flags to remove this in production code where it's not needed 26 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 27 | public class ConfigSourceInformationAttribute : Attribute { } 28 | 29 | /// Specifies a specific named value that should be read from the yaml 30 | /// and assigned to this field or property. Useful when you'd prefer to use 31 | /// different names in C# and yaml. 32 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 33 | public class ConfigKeyAttribute : Attribute { 34 | public string Key; 35 | 36 | /// 37 | /// Read the value corresponding to when 38 | /// reifying this value, rather than the value associated with the 39 | /// key that matches this field/property value's name. 40 | /// 41 | /// The substitute key 42 | public ConfigKeyAttribute(string key) { 43 | if (string.IsNullOrWhiteSpace(key)) { 44 | throw new ArgumentNullException(nameof(key)); 45 | } 46 | 47 | Key = key.Trim(); 48 | } 49 | } 50 | 51 | /// 52 | /// Marks this type as a polymorphic union of its parent type and indicates the key whose presence implies this type 53 | /// 54 | [AttributeUsage(AttributeTargets.Class)] 55 | public class ConfigUnionAttribute : Attribute { 56 | public readonly string Key; 57 | 58 | /// 59 | /// When parsing the parent type, if the key is then this type will be 60 | /// parsed instead. 61 | /// 62 | /// The substitute key 63 | public ConfigUnionAttribute(string key) { 64 | if (string.IsNullOrWhiteSpace(key)) { 65 | throw new ArgumentNullException(nameof(key)); 66 | } 67 | Key = key.Trim(); 68 | } 69 | } 70 | 71 | /// 72 | /// Marks this type as a polymorphic union of its parent type and indicates the key whose presence implies this type 73 | /// The key for this union is in the same doc as it's properties. The key is always the first property specified. 74 | /// 75 | [AttributeUsage(AttributeTargets.Class)] 76 | public class ConfigUnionInlineAttribute : Attribute { 77 | public readonly string Key; 78 | 79 | /// 80 | /// When parsing the parent type, if the key is then this type will be 81 | /// parsed instead. 82 | /// 83 | /// The substitute key 84 | public ConfigUnionInlineAttribute(string key) { 85 | if (string.IsNullOrWhiteSpace(key)) { 86 | throw new ArgumentNullException(nameof(key)); 87 | } 88 | Key = key.Trim(); 89 | } 90 | } 91 | 92 | /// If the field annotated with inline then we will look for it's properties in the same doc as the parent 93 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 94 | public class ConfigInlineAttribute : Attribute { } 95 | 96 | /// Name of this type in documentation. For generic types, "<0>" indicates the first template parameter, "<1>" the second, and so on. 97 | [AttributeUsage(AttributeTargets.Class)] 98 | public class ConfigDocumentationNameAttribute : Attribute { 99 | public readonly string Value; 100 | 101 | public ConfigDocumentationNameAttribute(string value) { 102 | Value = value; 103 | } 104 | } 105 | 106 | /// Description of this type or field 107 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, Inherited = false)] 108 | public class ConfigDocumentationDescriptionAttribute : Attribute { 109 | public readonly string Value; 110 | 111 | public ConfigDocumentationDescriptionAttribute(string value) { 112 | Value = value; 113 | } 114 | } 115 | 116 | /// Example yaml of this type 117 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true, Inherited = false)] 118 | public class ConfigDocumentationExampleAttribute : Attribute { 119 | public readonly string Value; 120 | 121 | public ConfigDocumentationExampleAttribute(string value) { 122 | Value = value; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/DarkConfig/ConfigFileInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DarkConfig { 4 | public class ConfigFileInfo { 5 | /// The identifier we use to refer to this file. 6 | /// Usually the relative config file path without the file extension. 7 | /// "Weapons/Swords/Rapier" for the file "./Weapons/Swords/Rapier.yaml" 8 | public readonly string Name; 9 | 10 | // File size. Used as a quick, coarse-grained checksum for hotloading. 11 | public long Size; 12 | 13 | /// Checksum of file contents. Used in hotloading. 14 | public int Checksum; 15 | 16 | /// Last modified time of the file when it was loaded. Used to detect changes when hotloading. 17 | public DateTime Modified; 18 | 19 | /// Parsed file contents. 20 | public DocNode Parsed; 21 | 22 | public ConfigFileInfo(string name, int checksum, long size, DateTime modified, DocNode parsed) { 23 | Name = name; 24 | Checksum = checksum; 25 | Size = size; 26 | Modified = modified; 27 | Parsed = parsed; 28 | } 29 | 30 | public override string ToString() { 31 | return $"[{Name} {Checksum:X16}]"; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/DarkConfig/ConfigProcessor.cs: -------------------------------------------------------------------------------- 1 | namespace DarkConfig { 2 | /// Processors can modify DocNodes after being parsed from YAML, but before used by the rest of the systems 3 | /// Note: this is ONLY run on the YAML -> DocNode path, any other DocNode creation is not affected 4 | public interface ConfigProcessor { 5 | /// Does this processor potentially mutate data 6 | /// Will make sure ComposedDocNode.MakeMutable() is run at least once before running this processor 7 | public bool CanMutate { get; } 8 | 9 | /// Process the DocNode here 10 | public void Process(string filename, ref DocNode doc); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/DarkConfig/ConfigSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace DarkConfig { 6 | /// A source of config files to load. 7 | /// e.g. a folder on disk, a binary file, a web server, etc. 8 | public abstract class ConfigSource { 9 | /// Does this config source support hotloading config files? 10 | public abstract bool CanHotload { get; } 11 | 12 | /// Generator function that finds and load all configs that this source knows about. 13 | /// Loads one file at a time, separated by a yield return null. 14 | /// Used for both blocking and time-sliced config loading. 15 | public abstract IEnumerable StepPreload(); 16 | 17 | /// Try to hotload config files. Adds names of changed files to the list. 18 | public virtual void Hotload(List changedFiles) { } 19 | 20 | /// 21 | /// Enumerates all file lists (aka keys in AllFiles) in sorted order. 22 | /// 23 | /// An enumeration of all the filename keys in sorted order 24 | public IEnumerable GetSortedFilenames() { 25 | foreach (string fileName in AllFiles.Keys.OrderBy(it => it)) { 26 | yield return fileName; 27 | } 28 | } 29 | 30 | ///////////////////////////////////////////////// 31 | 32 | /// All the currently loaded config file data. 33 | public Dictionary AllFiles = new(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/DarkConfig/DarkConfig.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | 9 6 | 7 | disable 8 | enable 9 | false 10 | ..\..\bin\$(Configuration) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/DarkConfig/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace DarkConfig { 5 | public class YamlFileException : Exception { 6 | public YamlFileException(string filename, YamlDotNet.Core.YamlException inner) 7 | : base($"Encountered error parsing YAML file '{filename}': {inner.Message}", inner) { 8 | Filename = filename; 9 | YamlException = inner; 10 | } 11 | 12 | public string Filename { get; private set; } 13 | public YamlDotNet.Core.YamlException YamlException { get; private set; } 14 | } 15 | 16 | /// The reason for this strange structure is that when Unity prints 17 | /// exceptions raised in the course of Reifying, often the info you need 18 | /// (the line number) is buried in the second or Nth exception. Unity 19 | /// prints exceptions by printing the message and StackTrace starting from 20 | /// the innermost exception, and working outwards. So this instead makes it 21 | /// more readable by putting all the messages up top, and then all the 22 | /// stack traces in a big line, still from inner at the top to outer at the 23 | /// bottom. It's a bit more readable, and most importantly the line 24 | /// numbers in the config files are much more prominent. 25 | public class ParseException : Exception { 26 | public ParseException(DocNode? exceptionNode, string message, Exception? inner = null) : base((inner != null ? inner.Message + "\n" : "") + message) { 27 | Node = exceptionNode; 28 | wrappedException = inner; 29 | } 30 | 31 | public override string? StackTrace => wrappedException == null ? base.StackTrace : wrappedException.StackTrace + "\n-----\n" + base.StackTrace; 32 | public override string Message => base.Message + (Node != null ? $" from {Node.SourceInformation}" : ""); 33 | public string RawMessage => base.Message; 34 | public bool HasNode => Node != null; 35 | 36 | public readonly DocNode? Node; 37 | readonly Exception? wrappedException; 38 | } 39 | 40 | public class TypedParseException : ParseException { 41 | public Type ParsedType; 42 | public TypedParseException(Type type, DocNode node, string message) : base(node, message) { 43 | ParsedType = type; 44 | } 45 | } 46 | 47 | public class MissingFieldsException : TypedParseException { 48 | public MissingFieldsException(Type type, DocNode node, string message) : base(type, node, message) { } 49 | } 50 | 51 | public class ExtraFieldsException : TypedParseException { 52 | public ExtraFieldsException(Type type, DocNode node, string message) : base(type, node, message) { } 53 | } 54 | 55 | public class ConfigFileNotFoundException : FileNotFoundException { 56 | public ConfigFileNotFoundException(string filename) : base("Couldn't find file " + filename + ". Perhaps it isn't in the index, or wasn't preloaded.", filename) { } 57 | } 58 | 59 | public class NotPreloadedException : InvalidOperationException { 60 | public NotPreloadedException(string message) : base(message) { } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/DarkConfig/Internal/BuiltInTypeReifiers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DarkConfig.Internal { 4 | static class BuiltInTypeReifiers { 5 | internal static object FromDateTime(object? existing, DocNode doc) { 6 | return DateTime.Parse(doc.StringValue, System.Globalization.CultureInfo.InvariantCulture); 7 | } 8 | 9 | internal static object FromTimeSpan(object? existing, DocNode doc) { 10 | bool isSuccess = TimeSpan.TryParse(doc.StringValue, out var newSpan); 11 | if (!isSuccess) { 12 | throw new ParseException(doc, "expected parseable timespan string " + doc.StringValue); 13 | } 14 | 15 | return newSpan; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DarkConfig/Internal/ChecksumUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace DarkConfig.Internal { 4 | public static class ChecksumUtils { 5 | /// Computes an integer checksum of a string. 6 | public static int Checksum(string body) { 7 | byte[] input = System.Text.Encoding.UTF8.GetBytes(body); 8 | using (MemoryStream stream = new MemoryStream(input)) { 9 | return MurMurHash3(stream); 10 | } 11 | } 12 | 13 | /// Computes an integer checksum of a stream. 14 | public static int Checksum(Stream stream) { 15 | return MurMurHash3(stream); 16 | } 17 | 18 | ///////////////////////////////////////////////// 19 | 20 | /// MurMurHash3 21 | /// This code is public domain. 22 | /// 23 | /// The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain. 24 | /// See http://code.google.com/p/smhasher/ 25 | /// 26 | /// This C# variant was authored by 27 | /// Elliott B. Edwards and was placed into the public domain as a gist 28 | private static int MurMurHash3(Stream stream) { 29 | const uint seed = 144; 30 | 31 | uint rotl32(uint x, byte r) { 32 | return (x << r) | (x >> (32 - r)); 33 | } 34 | 35 | uint fmix(uint h) { 36 | h ^= h >> 16; 37 | h *= 0x85ebca6b; 38 | h ^= h >> 13; 39 | h *= 0xc2b2ae35; 40 | h ^= h >> 16; 41 | return h; 42 | } 43 | 44 | const uint c1 = 0xcc9e2d51; 45 | const uint c2 = 0x1b873593; 46 | 47 | uint h1 = seed; 48 | uint k1 = 0; 49 | uint streamLength = 0; 50 | 51 | var reader = new BinaryReader(stream); 52 | 53 | byte[] chunk = reader.ReadBytes(4); 54 | while (chunk.Length > 0) { 55 | streamLength += (uint) chunk.Length; 56 | switch (chunk.Length) { 57 | case 4: 58 | /* Get four bytes from the input into an uint */ 59 | k1 = (uint) 60 | (chunk[0] 61 | | chunk[1] << 8 62 | | chunk[2] << 16 63 | | chunk[3] << 24); 64 | 65 | /* bitmagic hash */ 66 | k1 *= c1; 67 | k1 = rotl32(k1, 15); 68 | k1 *= c2; 69 | 70 | h1 ^= k1; 71 | h1 = rotl32(h1, 13); 72 | h1 = h1 * 5 + 0xe6546b64; 73 | break; 74 | case 3: 75 | k1 = (uint) 76 | (chunk[0] 77 | | chunk[1] << 8 78 | | chunk[2] << 16); 79 | k1 *= c1; 80 | k1 = rotl32(k1, 15); 81 | k1 *= c2; 82 | h1 ^= k1; 83 | break; 84 | case 2: 85 | k1 = (uint) 86 | (chunk[0] 87 | | chunk[1] << 8); 88 | k1 *= c1; 89 | k1 = rotl32(k1, 15); 90 | k1 *= c2; 91 | h1 ^= k1; 92 | break; 93 | case 1: 94 | k1 = (uint) (chunk[0]); 95 | k1 *= c1; 96 | k1 = rotl32(k1, 15); 97 | k1 *= c2; 98 | h1 ^= k1; 99 | break; 100 | } 101 | 102 | chunk = reader.ReadBytes(4); 103 | } 104 | 105 | // finalization, magic chants to wrap it all up 106 | h1 ^= streamLength; 107 | h1 = fmix(h1); 108 | 109 | unchecked { //ignore overflow 110 | return (int) h1; 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/DarkConfig/Internal/MultiCaseDictionary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | namespace DarkConfig.Internal { 7 | /// 8 | /// Dictionary that supports both case-sensitive and case-insensitive lookups while retaining the case of the key 9 | /// 10 | /// Type of values in the dictionary (keys are strings) 11 | internal class MultiCaseDictionary : IEnumerable<(string, TValueType)> { 12 | readonly Dictionary _dictionary; 13 | 14 | public MultiCaseDictionary() : this(0) { } 15 | 16 | public MultiCaseDictionary(int capacity) { 17 | _dictionary = new Dictionary(capacity, StringComparer.OrdinalIgnoreCase); 18 | } 19 | 20 | public bool TryGetValue(string key, [MaybeNullWhen(false)] out TValueType value, bool ignoreCase) { 21 | if (_dictionary.TryGetValue(key, out var match)) { 22 | if (ignoreCase) { 23 | value = match.Value; 24 | return true; 25 | } 26 | 27 | if (key.Equals(match.Key)) { 28 | value = match.Value; 29 | return true; 30 | } 31 | } 32 | 33 | value = default; 34 | return false; 35 | } 36 | 37 | public void Add(string key, TValueType value) { 38 | _dictionary.Add(key, (key, value)); 39 | } 40 | 41 | public bool TryAdd(string key, TValueType value) { 42 | return _dictionary.TryAdd(key, (key, value)); 43 | } 44 | 45 | public IEnumerator<(string, TValueType)> GetEnumerator() { 46 | return _dictionary.Values.GetEnumerator(); 47 | } 48 | 49 | IEnumerator IEnumerable.GetEnumerator() { 50 | return ((IEnumerable) _dictionary.Values).GetEnumerator(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/DarkConfig/Internal/RegexUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace DarkConfig.Internal { 5 | public static class RegexUtils { 6 | /// Returns a list of all the strings in the given list that match the given regex. 7 | public static void FilterMatching(Regex pattern, IEnumerable strings, List results) { 8 | foreach (string str in strings) { 9 | if (pattern.IsMatch(str)) { 10 | results.Add(str); 11 | } 12 | } 13 | } 14 | 15 | public static void FilterMatching(Regex pattern, IEnumerable strings, HashSet results) { 16 | foreach (string str in strings) { 17 | if (pattern.IsMatch(str)) { 18 | results.Add(str); 19 | } 20 | } 21 | } 22 | 23 | public static void FilterMatchingGlob(string glob, IEnumerable strings, List results) { 24 | FilterMatching(GlobToRegex(glob), strings, results); 25 | } 26 | 27 | public static void FilterMatchingGlob(string glob, IEnumerable strings, HashSet results) { 28 | FilterMatching(GlobToRegex(glob), strings, results); 29 | } 30 | 31 | /// Converts a glob-style expression into a file path regex 32 | /// '*' matches any sequence of characters, but stops at slashes 33 | /// '?' matches a single character, except a slash 34 | /// '**' matches any sequence of characters, including slashes 35 | public static Regex GlobToRegex(string glob) { 36 | var regexString = Regex.Escape(glob) 37 | .Replace(@"\*\*", @".*") 38 | .Replace(@"\*", @"[^/]*") 39 | .Replace(@"\?", @"[^/]"); 40 | var regex = new Regex("^" + regexString + "$", RegexOptions.IgnoreCase | RegexOptions.Singleline); 41 | return regex; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/DarkConfig/Internal/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DarkConfig.Internal { 2 | static class StringExtensions { 3 | /// Returns the lowercase version of the key if ignoreCase, otherwise return the key itself 4 | internal static string CanonicalizeKey(this string key, bool ignoreCase) { 5 | return ignoreCase ? key.ToLowerInvariant() : key; 6 | } 7 | 8 | /// Returns the hash of the lowercase version of the key if ignoreCase, otherwise return the hash of the key itself 9 | internal static int GetCanonicalHashCode(this string key, bool ignoreCase) { 10 | return ignoreCase ? key.ToLowerInvariant().GetHashCode() : key.GetHashCode(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DarkConfig/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DarkConfig { 4 | [Flags] 5 | public enum ReificationOptions { 6 | None = 0, 7 | 8 | /// fields present in the YAML document but not on the object are allowed 9 | AllowExtraFields = 1 << 0, 10 | 11 | /// fields present on the object but not in the YAML document are allowed 12 | AllowMissingFields = 1 << 1, 13 | 14 | /// both missing and extra fields are allowed 15 | AllowMissingExtraFields = AllowExtraFields | AllowMissingFields, 16 | 17 | /// properties care about case 18 | CaseSensitive = 1 << 2 19 | } 20 | 21 | public enum LogVerbosity { 22 | Warn, 23 | Info 24 | } 25 | 26 | public class Settings { 27 | /// Default options for reification. Change this if you want to change 28 | /// DarkConfig behavior without passing in parameters to each call. 29 | public ReificationOptions DefaultReifierOptions = ReificationOptions.AllowMissingExtraFields | ReificationOptions.CaseSensitive; 30 | 31 | /// How aggressively DarkConfig logs 32 | public LogVerbosity LogLevel = LogVerbosity.Info; 33 | 34 | /// If enabled DarkConfig will scan files for changes every HotloadCheckInterval seconds. 35 | /// Setting it to false stops hotloading. Useful during production when configs are under rapid iteration. 36 | public bool EnableHotloading { 37 | get => Configs.FileManager.IsHotloadingFiles; 38 | set => Configs.FileManager.IsHotloadingFiles = value; 39 | } 40 | 41 | /// How often, in seconds, to scan files for changes. 42 | public float HotloadCheckFrequencySeconds = 2f; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/ConfigKeyTests.cs: -------------------------------------------------------------------------------- 1 | using DarkConfig; 2 | using NUnit.Framework; 3 | using System; 4 | 5 | [TestFixture] 6 | class ConfigKeyTests { 7 | 8 | class TestType { 9 | [ConfigKey("level")] 10 | public int CurrentLevel = 1; 11 | 12 | [ConfigKey("StartingXP")] 13 | public int XP { get; set; } = 5; 14 | } 15 | 16 | [Test] 17 | public void ConfigKeyAttributeChangesParsing() { 18 | const string yaml = "{level: 42, StartingXP: 99}"; 19 | var doc = Configs.ParseString(yaml, "ConfigKeyAttributeChangesParsing"); 20 | var instance = new TestType(); 21 | Configs.Reify(ref instance, doc); 22 | 23 | Assert.Multiple(() => { 24 | Assert.That(instance, Is.Not.Null); 25 | Assert.That(instance.CurrentLevel, Is.EqualTo(42)); 26 | Assert.That(instance.XP, Is.EqualTo(99)); 27 | }); 28 | } 29 | 30 | class NullKeyClass { 31 | [ConfigKey(null)] 32 | #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value 33 | public int fail; 34 | #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value 35 | } 36 | 37 | [Test] 38 | public void SettingANullKeyNameThrows() { 39 | const string yaml = "{fail: 42}"; 40 | var doc = Configs.ParseString(yaml, "SettingANullKeyNameThrows"); 41 | var instance = new NullKeyClass(); 42 | 43 | Assert.Throws(() => { 44 | Configs.Reify(ref instance, doc); 45 | }); 46 | } 47 | 48 | class EmptyKeyClass { 49 | [ConfigKey("")] 50 | #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value 51 | public int fail; 52 | #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value 53 | } 54 | 55 | [Test] 56 | public void SettingAnEmptyKeyNameThrows() { 57 | const string yaml = "{fail: 42}"; 58 | var doc = Configs.ParseString(yaml, "SettingAnEmptyKeyNameThrows"); 59 | var instance = new EmptyKeyClass(); 60 | 61 | Assert.Throws(() => { 62 | Configs.Reify(ref instance, doc); 63 | }); 64 | } 65 | 66 | class WhitespaceKeyClass { 67 | [ConfigKey(" ")] 68 | #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value 69 | public int fail; 70 | #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value 71 | } 72 | 73 | [Test] 74 | public void SettingAnAllWhitespaceKeyNameThrows() { 75 | const string yaml = "{fail: 42}"; 76 | var doc = Configs.ParseString(yaml, "SettingAnAllWhitespaceKeyNameThrows"); 77 | var instance = new WhitespaceKeyClass(); 78 | 79 | Assert.Throws(() => { 80 | Configs.Reify(ref instance, doc); 81 | }); 82 | } 83 | 84 | class PaddedKeyClass { 85 | [ConfigKey(" after ")] 86 | #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value 87 | public int before; 88 | #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value 89 | } 90 | 91 | [Test] 92 | public void KeyNamesAreTrimmed() { 93 | const string yaml = "{after: 42}"; 94 | var doc = Configs.ParseString(yaml, "SettingAnAllWhitespaceKeyNameThrows"); 95 | var instance = new PaddedKeyClass(); 96 | Configs.Reify(ref instance, doc); 97 | 98 | Assert.That(instance.before, Is.EqualTo(42)); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /test/DarkConfig.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | disable 5 | disable 6 | 7 | false 8 | 9 | false 10 | ..\bin\$(Configuration)_Test 11 | 9 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/DictComposingTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NUnit.Framework; 3 | using DarkConfig; 4 | 5 | [TestFixture] 6 | class DictComposingTests { 7 | string tempDirPath; 8 | FileSource fileSource; 9 | 10 | void CreateFile(string filename, string contents) { 11 | File.WriteAllText(Path.Combine(tempDirPath, filename), contents); 12 | } 13 | 14 | [SetUp] 15 | public void SetUp() { 16 | tempDirPath = Path.Combine(Path.GetTempPath(), "DictComposingTests"); 17 | Directory.CreateDirectory(tempDirPath); 18 | 19 | Configs.Settings.EnableHotloading = true; 20 | Configs.Settings.HotloadCheckFrequencySeconds = 0.1f; 21 | fileSource = new FileSource(tempDirPath, hotload: true); 22 | Configs.AddConfigSource(fileSource); 23 | } 24 | 25 | [TearDown] 26 | public void TearDown() { 27 | Directory.Delete(tempDirPath, true); 28 | Configs.Clear(); 29 | } 30 | 31 | [Test] 32 | public void MergedDict() { 33 | CreateFile("globals.yaml", "Beetles: 12\nBirdName: Shabazz\nVersion: 1.2"); 34 | CreateFile("items.yaml", "Treehouse: true"); 35 | CreateFile("rooms.yaml", "Version: 1.3\nrooms:\n - Overthorax\n - Chirpinghouse\n - Antennagate\n - Subchitin"); 36 | 37 | Configs.Preload(); 38 | 39 | DocNode MixedDict = null; 40 | 41 | // load all files from the DictDir into one dict 42 | Configs.ParseFilesAsMergedDict("*", d => { 43 | MixedDict = d; 44 | return true; 45 | }); 46 | 47 | Assert.Multiple(() => { 48 | Assert.That(MixedDict, Is.Not.Null); 49 | Assert.That(MixedDict, Has.Count.EqualTo(5)); 50 | Assert.That(MixedDict["Beetles"].As(), Is.EqualTo(12)); 51 | Assert.That(MixedDict["Version"].As(), Is.EqualTo(1.3f)); 52 | Assert.That(MixedDict["Treehouse"].As(), Is.True); 53 | }); 54 | 55 | // Overwrite file contents 56 | CreateFile("items.yaml", "Chitin: 1000"); 57 | 58 | // force a reload 59 | Configs.Update(1.0f); 60 | 61 | Assert.Multiple(() => { 62 | Assert.That(MixedDict, Has.Count.EqualTo(5)); 63 | Assert.That(MixedDict.ContainsKey("Treehouse"), Is.False); 64 | Assert.That(MixedDict["Chitin"].As(), Is.EqualTo(1000)); 65 | }); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/DocNodeExtensionTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using DarkConfig; 3 | using System.Collections.Generic; 4 | 5 | [TestFixture] 6 | class DocNodeExtensionTests { 7 | [Test] 8 | public void AsInt_Parses() { 9 | var doc = Configs.ParseString("10", "TestFilename"); 10 | Assert.That(doc.As(), Is.EqualTo(10)); 11 | } 12 | 13 | [Test] 14 | public void AsInt_Fails() { 15 | var doc = Configs.ParseString("not_an_int", "TestFilename"); 16 | Assert.Throws(() => { doc.As(); }); 17 | } 18 | 19 | [Test] 20 | public void AsFloat_Parses() { 21 | var doc = Configs.ParseString("1.45", "TestFilename"); 22 | Assert.That(doc.As(), Is.EqualTo(1.45f)); 23 | } 24 | 25 | [Test] 26 | public void AsString_Parses() { 27 | var doc = Configs.ParseString("derpy horse", "TestFilename"); 28 | Assert.That(doc.As(), Is.EqualTo("derpy horse")); 29 | } 30 | 31 | [Test] 32 | public void AsBool_Parses() { 33 | var doc = Configs.ParseString("true", "TestFilename"); 34 | Assert.That(doc.As(), Is.True); 35 | } 36 | 37 | [Test] 38 | public void NestedAccess_Dictionaries() { 39 | const string yaml = @"--- 40 | key: 41 | nested: 42 | final: 123 43 | "; 44 | var doc = Configs.ParseString(yaml, "TestFilename"); 45 | Assert.That(doc["key"]["nested"]["final"].As(), Is.EqualTo(123)); 46 | } 47 | 48 | [Test] 49 | public void NestedAccess_Lists() { 50 | const string yaml = @"--- 51 | key: 52 | - 9 53 | - 8.8 54 | - 7.1 55 | "; 56 | var doc = Configs.ParseString(yaml, "TestFilename"); 57 | Assert.Multiple(() => { 58 | Assert.That(doc["key"][1].As(), Is.EqualTo(8.8f)); 59 | Assert.That(doc["key"][2].As(), Is.EqualTo(7.1f)); 60 | }); 61 | } 62 | 63 | [Test] 64 | public void As_ListOfString() { 65 | const string yaml = @"--- 66 | - the 67 | - quick 68 | - brown 69 | - fox 70 | "; 71 | var doc = Configs.ParseString(yaml, "TestFilename"); 72 | var list = doc.As>(); 73 | Assert.Multiple(() => { 74 | Assert.That(list[0], Is.EqualTo("the")); 75 | Assert.That(list[1], Is.EqualTo("quick")); 76 | Assert.That(list[2], Is.EqualTo("brown")); 77 | Assert.That(list[3], Is.EqualTo("fox")); 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /test/FromDocTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using DarkConfig; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | [TestFixture] 7 | class FromDocTests { 8 | class TestClass { 9 | public int baseKey; 10 | 11 | public static TestClass FromDoc(TestClass existing, DocNode doc) { 12 | if (doc.Type != DocNodeType.List) { 13 | throw new System.ArgumentException("Not a list! " + doc.Type); 14 | } 15 | 16 | if (doc[0].StringValue == "Derived") { 17 | TestClassDerived derivedExisting; 18 | if (existing is TestClassDerived) { 19 | derivedExisting = (TestClassDerived) existing; 20 | } else { 21 | derivedExisting = new TestClassDerived(); 22 | } 23 | 24 | derivedExisting.derivedKey = 25 | Convert.ToInt32(doc[1].StringValue, System.Globalization.CultureInfo.InvariantCulture); 26 | return derivedExisting; 27 | } else { 28 | if (!(existing is TestClass)) { 29 | existing = new TestClass(); 30 | } 31 | 32 | existing.baseKey = 33 | Convert.ToInt32(doc[1].StringValue, System.Globalization.CultureInfo.InvariantCulture); 34 | return existing; 35 | } 36 | } 37 | } 38 | 39 | class TestClassDerived : TestClass { 40 | public int derivedKey; 41 | } 42 | 43 | const string FILENAME = "FromDocTests_TestFileName"; 44 | 45 | T ReifyString(string str) where T : new() { 46 | var doc = Configs.ParseString(str, "FromDocTests_ReifyString_TestFileName"); 47 | var instance = default(T); 48 | Configs.Reify(ref instance, doc); 49 | return instance; 50 | } 51 | 52 | [Test] 53 | public void FromDoc_CalledToReify() { 54 | var tc = ReifyString("[\"Base\", 12]"); 55 | Assert.That(tc.baseKey, Is.EqualTo(12)); 56 | } 57 | 58 | [Test] 59 | public void FromDoc_SpawnsDerivedClass() { 60 | var tc = ReifyString("[\"Derived\", 12]"); 61 | Assert.Multiple(() => { 62 | Assert.That(tc.baseKey, Is.EqualTo(0)); 63 | Assert.That(tc, Is.InstanceOf()); 64 | }); 65 | } 66 | 67 | [Test] 68 | public void FromDoc_UpdatesTestClass() { 69 | var tc = new TestClass {baseKey = 15}; 70 | var saved = tc; 71 | var doc = Configs.ParseString("[\"Base\", 99]", FILENAME); 72 | Configs.Reify(ref tc, doc); 73 | Assert.Multiple(() => { 74 | Assert.That(saved, Is.SameAs(tc)); 75 | Assert.That(tc.baseKey, Is.EqualTo(99)); 76 | }); 77 | } 78 | 79 | [Test] 80 | public void FromDoc_UpdatesDerived() { 81 | TestClass tc = new TestClassDerived {baseKey = 1, derivedKey = 2}; 82 | var saved = tc; 83 | var doc = Configs.ParseString("[\"Derived\", 66]", FILENAME); 84 | Configs.Reify(ref tc, doc); 85 | Assert.Multiple(() => { 86 | Assert.That(saved, Is.SameAs(tc)); 87 | Assert.That(tc.baseKey, Is.EqualTo(1)); 88 | Assert.That(((TestClassDerived) tc).derivedKey, Is.EqualTo(66)); 89 | }); 90 | } 91 | 92 | [Test] 93 | public void FromDoc_UpdatesDerived_AsBase() { 94 | TestClass tc = new TestClassDerived {baseKey = 4, derivedKey = 5}; 95 | var saved = tc; 96 | var doc = Configs.ParseString("[\"Base\", 123]", FILENAME); 97 | Configs.Reify(ref tc, doc); 98 | Assert.Multiple(() => { 99 | Assert.That(saved, Is.SameAs(tc)); 100 | Assert.That(tc.baseKey, Is.EqualTo(123)); 101 | Assert.That(((TestClassDerived) tc).derivedKey, Is.EqualTo(5)); 102 | }); 103 | } 104 | 105 | [Test] 106 | public void FromDoc_OverwritesBase_WithDerived() { 107 | var tc = new TestClass {baseKey = 19}; 108 | var saved = tc; 109 | var doc = Configs.ParseString("[\"Derived\", 321]", FILENAME); 110 | Configs.Reify(ref tc, doc); 111 | Assert.Multiple(() => { 112 | Assert.That(ReferenceEquals(tc, saved), Is.False); 113 | Assert.That(tc, Is.InstanceOf()); 114 | Assert.That(((TestClassDerived) tc).derivedKey, Is.EqualTo(321)); 115 | }); 116 | } 117 | 118 | [Test] 119 | [Ignore("It's not completely clear how we should call parent class FromDocs when reifying a derived object")] 120 | public void FromDoc_SpawnsDerivedClass_WhenCastAsDerived() { 121 | var tc = ReifyString("[\"Derived\", 12]"); 122 | Assert.That(tc.baseKey, Is.EqualTo(0)); 123 | } 124 | 125 | [Test] 126 | public void FromDoc_WrapsExceptions() { 127 | Assert.Throws(() => { ReifyString("{\"wrong\": \"structure\"}"); }); 128 | } 129 | 130 | [Test] 131 | public void FromDoc_CalledWhenReifyingNullClass() { 132 | TestClass tc = null; 133 | var doc = Configs.ParseString("[\"Base\", 451]", FILENAME); 134 | Configs.Reify(ref tc, doc); 135 | Assert.Multiple(() => { 136 | Assert.That(tc, Is.Not.Null); 137 | Assert.That(tc.baseKey, Is.EqualTo(451)); 138 | }); 139 | } 140 | 141 | [Test] 142 | public void FromDoc_CalledWhenReifyingEmptyList() { 143 | var lst = new List(); 144 | var doc = Configs.ParseString("[[\"Base\", 451]]", FILENAME); 145 | Configs.Reify(ref lst, doc); 146 | Assert.Multiple(() => { 147 | Assert.That(lst, Has.Count.EqualTo(1)); 148 | Assert.That(lst[0].baseKey, Is.EqualTo(451)); 149 | }); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /test/GlobMatchTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections.Generic; 3 | using DarkConfig.Internal; 4 | 5 | [TestFixture] 6 | class GlobMatchTests { 7 | static readonly List AllFiles = new List { 8 | "Folder/1File", 9 | "Folder/2File", 10 | "Folder/3File", 11 | "Folder/Thumbs", 12 | "Uggabo", 13 | "Buggabo", 14 | "Parent/Child/Grandchild/a", 15 | "Parent/Child/Grandchild/b", 16 | "Parent/Child/Grandchild/c", 17 | }; 18 | 19 | [Test] 20 | public void MatchStar() { 21 | var matchingFiles = new List(); 22 | RegexUtils.FilterMatchingGlob("Folder/*", AllFiles, matchingFiles); 23 | Assert.That(matchingFiles, Is.EqualTo(new List {"Folder/1File", "Folder/2File", "Folder/3File", "Folder/Thumbs"})); 24 | } 25 | 26 | [Test] 27 | public void MatchStarPostfix() { 28 | var matchingFiles = new List(); 29 | RegexUtils.FilterMatchingGlob("Folder/*File", AllFiles, matchingFiles); 30 | Assert.That(matchingFiles, Is.EqualTo(new List {"Folder/1File", "Folder/2File", "Folder/3File"})); 31 | } 32 | 33 | [Test] 34 | public void MatchQuestionMark() { 35 | var matchingFiles = new List(); 36 | RegexUtils.FilterMatchingGlob("Folder/?File", AllFiles, matchingFiles); 37 | Assert.That(matchingFiles, Is.EqualTo(new List {"Folder/1File", "Folder/2File", "Folder/3File"})); 38 | } 39 | 40 | [Test] 41 | public void MatchStarOnePathOnly() { 42 | var matchingFiles = new List(); 43 | RegexUtils.FilterMatchingGlob("*", AllFiles, matchingFiles); 44 | Assert.That(matchingFiles, Is.EqualTo(new List {"Uggabo", "Buggabo"})); 45 | } 46 | 47 | [Test] 48 | public void MatchDoubleStar() { 49 | var matchingFiles = new List(); 50 | RegexUtils.FilterMatchingGlob("Parent/**", AllFiles, matchingFiles); 51 | Assert.That(matchingFiles, Is.EqualTo(new List {"Parent/Child/Grandchild/a", "Parent/Child/Grandchild/b", "Parent/Child/Grandchild/c"})); 52 | } 53 | 54 | [Test] 55 | public void MatchDoubleStarCapped() { 56 | var matchingFiles = new List(); 57 | RegexUtils.FilterMatchingGlob("Parent/**/b", AllFiles, matchingFiles); 58 | Assert.That(matchingFiles, Is.EqualTo(new List {"Parent/Child/Grandchild/b"})); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/ListComposingTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NUnit.Framework; 3 | using DarkConfig; 4 | using System.Collections.Generic; 5 | 6 | [TestFixture] 7 | class ListComposingTests { 8 | class Character { 9 | public int Height = 0; 10 | public string Item = ""; 11 | } 12 | 13 | string tempDirPath; 14 | 15 | void CreateFile(string filename, string contents) { 16 | string fullPath = Path.Combine(tempDirPath, filename); 17 | using var sw = new StreamWriter(fullPath, false, new System.Text.UTF8Encoding()); 18 | sw.Write(contents); 19 | } 20 | 21 | [SetUp] 22 | public void SetUp() { 23 | tempDirPath = Path.Combine(Path.GetTempPath(), "ListComposingTests"); 24 | Directory.CreateDirectory(tempDirPath); 25 | 26 | Configs.Settings.EnableHotloading = true; 27 | Configs.Settings.HotloadCheckFrequencySeconds = 0.1f; 28 | Configs.AddConfigSource(new FileSource(tempDirPath, hotload: true)); 29 | } 30 | 31 | [TearDown] 32 | public void TearDown() { 33 | Directory.Delete(tempDirPath, true); 34 | Configs.Clear(); 35 | } 36 | 37 | [Test] 38 | public void MergeList() { 39 | CreateFile("aragorn.yaml", "Height: 12\nItem: Anduril"); 40 | CreateFile("arathorn.yaml", "Height: 11\nItem: Son"); 41 | CreateFile("beorn.yaml", "Height: 18\nItem: Bear"); 42 | CreateFile("celeborn.yaml", "Height: 14\nItem: Silver"); 43 | 44 | Configs.Preload(); 45 | 46 | var CharactersEndingInOrn = new List(); 47 | 48 | // load all files from the ListDir into one list 49 | Configs.ParseFilesAsList("*", d => { 50 | Assert.That(d.Count, Is.EqualTo(4)); 51 | Configs.Reify(ref CharactersEndingInOrn, d); 52 | return true; 53 | }); 54 | 55 | Assert.Multiple(() => { 56 | Assert.That(CharactersEndingInOrn, Has.Count.EqualTo(4)); 57 | Assert.That(CharactersEndingInOrn[0].Height, Is.EqualTo(12)); 58 | Assert.That(CharactersEndingInOrn[0].Item, Is.EqualTo("Anduril")); 59 | }); 60 | 61 | // change file contents 62 | CreateFile("aragorn.yaml", "Height: 12\nItem: Throne"); 63 | 64 | // Force hotload 65 | Configs.Update(1.0f); 66 | 67 | Assert.Multiple(() => { 68 | Assert.That(CharactersEndingInOrn, Has.Count.EqualTo(4)); 69 | Assert.That(CharactersEndingInOrn[0].Height, Is.EqualTo(12)); 70 | Assert.That(CharactersEndingInOrn[0].Item, Is.EqualTo("Throne")); 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/MissingFilesTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NUnit.Framework; 3 | using DarkConfig; 4 | using System.Text.RegularExpressions; 5 | 6 | [TestFixture] 7 | class MissingFilesTests { 8 | string tempDirPath; 9 | 10 | void CreateFile(string filename, string contents) { 11 | var fullPath = Path.Combine(tempDirPath, filename); 12 | using (var sw = new StreamWriter(fullPath, false, new System.Text.UTF8Encoding())) { 13 | sw.Write(contents); 14 | } 15 | } 16 | 17 | [SetUp] 18 | public void SetUp() { 19 | tempDirPath = Path.Combine(Path.GetTempPath(), "ListComposingTests"); 20 | Directory.CreateDirectory(tempDirPath); 21 | 22 | Configs.Settings.EnableHotloading = true; 23 | Configs.Settings.HotloadCheckFrequencySeconds = 0.1f; 24 | Configs.AddConfigSource(new FileSource(tempDirPath, hotload: true)); 25 | } 26 | 27 | [TearDown] 28 | public void TearDown() { 29 | Directory.Delete(tempDirPath, true); 30 | Configs.Clear(); 31 | } 32 | 33 | [Test] 34 | public void MissingFiles() { 35 | CreateFile("spinner.yaml", "key: ok"); 36 | 37 | Configs.Preload(); 38 | 39 | // check the index after preload 40 | var filenames = Configs.GetFilenamesMatchingRegex(new Regex(".*")); 41 | Assert.Greater(filenames.Count, 0); 42 | 43 | Assert.IsTrue(filenames.Contains("spinner")); 44 | 45 | // check that we can load existing files 46 | var spinnerDoc = Configs.ParseFile("spinner"); 47 | 48 | // this file should be present so this should pass 49 | Assert.IsTrue(spinnerDoc.ContainsKey("key")); 50 | 51 | Assert.Throws(() => { 52 | Configs.ParseFile("nonexistent", (d) => { 53 | Assert.Fail("Callback shouldn't be called"); 54 | return false; 55 | }); 56 | }); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/PostDocTests.cs: -------------------------------------------------------------------------------- 1 | using DarkConfig; 2 | using NUnit.Framework; 3 | 4 | [TestFixture] 5 | class PostDocTests { 6 | const string FILENAME = "PostDocTests_TestFilename"; 7 | 8 | class PostDocClass { 9 | public static PostDocClass PostDoc(PostDocClass existing) { 10 | existing.baseKey += 1; 11 | return existing; 12 | } 13 | 14 | public int baseKey; 15 | } 16 | 17 | class PostDocClass2 { 18 | public int baseKey = 0; 19 | } 20 | 21 | class PostDocClass3 { 22 | public static PostDocClass3 PostDoc(PostDocClass3 existing) { 23 | return new PostDocClass3 { 24 | baseKey = 99 25 | }; 26 | } 27 | 28 | public int baseKey; 29 | } 30 | 31 | static T ReifyString(string str) where T : new() { 32 | var doc = Configs.ParseString(str, FILENAME); 33 | var result = default(T); 34 | Configs.Reify(ref result, doc); 35 | return result; 36 | } 37 | 38 | [Test] 39 | public void PostDoc_IsCalled() { 40 | var instance = ReifyString("baseKey: 10"); 41 | Assert.That(instance.baseKey, Is.EqualTo(11)); 42 | } 43 | 44 | [Test] 45 | public void PostDoc_DoesntExist() { 46 | var doc = Configs.ParseString("baseKey: 10", FILENAME); 47 | PostDocClass2 instance = null; 48 | Configs.Reify(ref instance, doc); 49 | Assert.Multiple(() => { 50 | Assert.That(instance, Is.Not.Null); 51 | Assert.That(instance.baseKey, Is.EqualTo(10)); 52 | }); 53 | } 54 | 55 | [Test] 56 | public void PostDoc_CanReplaceWithReturnValue() { 57 | var doc = Configs.ParseString("baseKey: 10", FILENAME); 58 | PostDocClass3 instance = null; 59 | Configs.Reify(ref instance, doc); 60 | Assert.Multiple(() => { 61 | Assert.That(instance, Is.Not.Null); 62 | Assert.That(instance.baseKey, Is.EqualTo(99)); 63 | }); 64 | } 65 | 66 | [Test] 67 | public void PostDoc_ManuallyRegistered() { 68 | var doc = Configs.ParseString("baseKey: 5", FILENAME); 69 | PostDocClass2 instance = null; 70 | Configs.RegisterPostDoc(instance => { 71 | return new PostDocClass2 {baseKey = 10}; 72 | }); 73 | Configs.Reify(ref instance, doc); 74 | Assert.Multiple(() => { 75 | Assert.That(instance, Is.Not.Null); 76 | Assert.That(instance.baseKey, Is.EqualTo(10)); 77 | }); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /test/YamlParseTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using System.IO; 4 | using YamlDotNet.RepresentationModel; 5 | using DarkConfig; 6 | 7 | [TestFixture] 8 | public class YamlParseTests { 9 | static YamlNode ParseYamlNode(string str) { 10 | var yaml = new YamlStream(); 11 | yaml.Load(new StringReader(str)); 12 | return yaml.Documents[0].RootNode; 13 | } 14 | 15 | [TestFixture] 16 | public class YamlDocParser { 17 | [Test] 18 | public void JsonSubset_TraversedByDocNode() { 19 | string testStr = "{\"test_key\":\"test_value\"}"; 20 | var dn = (DocNode) new YamlDocNode(ParseYamlNode(testStr), "testfilename"); 21 | Assert.Multiple(() => { 22 | Assert.That(dn, Has.Count.EqualTo(1)); 23 | Assert.That(dn["test_key"].StringValue, Is.EqualTo("test_value")); 24 | Assert.That(dn.ContainsKey("test_key"), Is.True); 25 | }); 26 | foreach (var entry in dn.Pairs) { 27 | Assert.Multiple(() => { 28 | Assert.That(entry.Key, Is.EqualTo("test_key")); 29 | Assert.That(entry.Value.StringValue, Is.EqualTo("test_value")); 30 | }); 31 | } 32 | } 33 | 34 | [Test] 35 | public void DocNodeDictionaryAccess_ThrowsWhenIndexed() { 36 | string testStr = @"--- 37 | # interrupting comment 38 | key: 39 | inner_key: value 40 | "; 41 | var dn = (DocNode) new YamlDocNode(ParseYamlNode(testStr), "testfilename"); 42 | 43 | var exception = Assert.Throws(() => { 44 | var x = dn["key"][3]; 45 | }); 46 | 47 | Assert.Multiple(() => { 48 | Assert.That(exception, Is.Not.Null); 49 | 50 | // verify that there's a line number in the exception 51 | Assert.That(exception.Message.IndexOf("Line: 4", StringComparison.Ordinal), Is.GreaterThanOrEqualTo(0)); 52 | 53 | // verify that the dummy filename that we passed in shows up in the exception message 54 | Assert.That(exception.Message.IndexOf("testfilename", StringComparison.Ordinal), Is.GreaterThanOrEqualTo(0)); 55 | }); 56 | } 57 | } 58 | } 59 | --------------------------------------------------------------------------------