├── .gitattributes ├── .gitignore ├── Beat-360fyer.sln ├── Beat-360fyer ├── 360.png ├── App.config ├── Beat-360fyer.csproj ├── BeatMap.cs ├── BeatMapGenerator.cs ├── BeatMapGeneratorAttribute.cs ├── BeatMapGeneratorConfig.cs ├── BeatMapInfo.cs ├── Config.cs ├── Everaldo-Starwars-Darth-Mauls-light-sabers.ico ├── FileEnumerator.cs ├── FormGeneratePack.Designer.cs ├── FormGeneratePack.cs ├── FormGeneratePack.resx ├── FormGeneratorSettings.Designer.cs ├── FormGeneratorSettings.cs ├── FormGeneratorSettings.resx ├── Generators │ ├── BeatMap360Generator.cs │ └── ExampleGenerator.cs ├── GitHubBasedUpdateCheck.cs ├── HashSetExtensions.cs ├── IBeatMapGenerator.cs ├── ICloneable.cs ├── Jobs.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── ThreeSixtyfyerConfig.cs ├── WorkerJob.cs └── packages.config ├── Build ├── 360.png ├── Beat-360fyer v1.0.zip ├── Beat-360fyer v2.0.zip ├── Demos │ ├── Beat It.zip │ ├── Beat it (old version).zip │ ├── Boulevard of Broken Dreams.zip │ ├── Jaroslav Beck - Beat Saber (old version).zip │ ├── Pokemon Theme Song.zip │ ├── Riot - Overkill.zip │ └── beatsaber.gif ├── latestVersion.txt └── sabers.ico ├── LICENSE ├── README.md └── Research ├── Jaroslav Beck - Beat Saber ├── 360DegreeEasy.dat ├── 360DegreeExpert.dat ├── 360DegreeExpertPlus.dat ├── 360DegreeHard.dat ├── 90DegreeEasy.dat ├── Easy.dat ├── Expert.dat ├── ExpertPlus.dat ├── Hard.dat ├── Info.dat ├── NoArrowsEasy.dat ├── NoArrowsExpert.dat ├── NoArrowsHard.dat ├── NoArrowsNormal.dat ├── Normal.dat ├── OneSaberExpert.dat ├── cover.png └── song.ogg ├── Testing map ├── Easy.dat ├── Screenshot_1.png ├── Screenshot_2.png ├── Screenshot_2_.png ├── Screenshot_3.png ├── cover.jpg ├── info.dat └── song.egg └── events.xlsx /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.vspscc 94 | *.vssscc 95 | .builds 96 | *.pidb 97 | *.svclog 98 | *.scc 99 | 100 | # Chutzpah Test files 101 | _Chutzpah* 102 | 103 | # Visual C++ cache files 104 | ipch/ 105 | *.aps 106 | *.ncb 107 | *.opendb 108 | *.opensdf 109 | *.sdf 110 | *.cachefile 111 | *.VC.db 112 | *.VC.VC.opendb 113 | 114 | # Visual Studio profiler 115 | *.psess 116 | *.vsp 117 | *.vspx 118 | *.sap 119 | 120 | # Visual Studio Trace Files 121 | *.e2e 122 | 123 | # TFS 2012 Local Workspace 124 | $tf/ 125 | 126 | # Guidance Automation Toolkit 127 | *.gpState 128 | 129 | # ReSharper is a .NET coding add-in 130 | _ReSharper*/ 131 | *.[Rr]e[Ss]harper 132 | *.DotSettings.user 133 | 134 | # TeamCity is a build add-in 135 | _TeamCity* 136 | 137 | # DotCover is a Code Coverage Tool 138 | *.dotCover 139 | 140 | # AxoCover is a Code Coverage Tool 141 | .axoCover/* 142 | !.axoCover/settings.json 143 | 144 | # Coverlet is a free, cross platform Code Coverage Tool 145 | coverage*.json 146 | coverage*.xml 147 | coverage*.info 148 | 149 | # Visual Studio code coverage results 150 | *.coverage 151 | *.coveragexml 152 | 153 | # NCrunch 154 | _NCrunch_* 155 | .*crunch*.local.xml 156 | nCrunchTemp_* 157 | 158 | # MightyMoose 159 | *.mm.* 160 | AutoTest.Net/ 161 | 162 | # Web workbench (sass) 163 | .sass-cache/ 164 | 165 | # Installshield output folder 166 | [Ee]xpress/ 167 | 168 | # DocProject is a documentation generator add-in 169 | DocProject/buildhelp/ 170 | DocProject/Help/*.HxT 171 | DocProject/Help/*.HxC 172 | DocProject/Help/*.hhc 173 | DocProject/Help/*.hhk 174 | DocProject/Help/*.hhp 175 | DocProject/Help/Html2 176 | DocProject/Help/html 177 | 178 | # Click-Once directory 179 | publish/ 180 | 181 | # Publish Web Output 182 | *.[Pp]ublish.xml 183 | *.azurePubxml 184 | # Note: Comment the next line if you want to checkin your web deploy settings, 185 | # but database connection strings (with potential passwords) will be unencrypted 186 | *.pubxml 187 | *.publishproj 188 | 189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 190 | # checkin your Azure Web App publish settings, but sensitive information contained 191 | # in these scripts will be unencrypted 192 | PublishScripts/ 193 | 194 | # NuGet Packages 195 | *.nupkg 196 | # NuGet Symbol Packages 197 | *.snupkg 198 | # The packages folder can be ignored because of Package Restore 199 | **/[Pp]ackages/* 200 | # except build/, which is used as an MSBuild target. 201 | !**/[Pp]ackages/build/ 202 | # Uncomment if necessary however generally it will be regenerated when needed 203 | #!**/[Pp]ackages/repositories.config 204 | # NuGet v3's project.json files produces more ignorable files 205 | *.nuget.props 206 | *.nuget.targets 207 | 208 | # Microsoft Azure Build Output 209 | csx/ 210 | *.build.csdef 211 | 212 | # Microsoft Azure Emulator 213 | ecf/ 214 | rcf/ 215 | 216 | # Windows Store app package directories and files 217 | AppPackages/ 218 | BundleArtifacts/ 219 | Package.StoreAssociation.xml 220 | _pkginfo.txt 221 | *.appx 222 | *.appxbundle 223 | *.appxupload 224 | 225 | # Visual Studio cache files 226 | # files ending in .cache can be ignored 227 | *.[Cc]ache 228 | # but keep track of directories ending in .cache 229 | !?*.[Cc]ache/ 230 | 231 | # Others 232 | ClientBin/ 233 | ~$* 234 | *~ 235 | *.dbmdl 236 | *.dbproj.schemaview 237 | *.jfm 238 | *.pfx 239 | *.publishsettings 240 | orleans.codegen.cs 241 | 242 | # Including strong name files can present a security risk 243 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 244 | #*.snk 245 | 246 | # Since there are multiple workflows, uncomment next line to ignore bower_components 247 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 248 | #bower_components/ 249 | 250 | # RIA/Silverlight projects 251 | Generated_Code/ 252 | 253 | # Backup & report files from converting an old project file 254 | # to a newer Visual Studio version. Backup files are not needed, 255 | # because we have git ;-) 256 | _UpgradeReport_Files/ 257 | Backup*/ 258 | UpgradeLog*.XML 259 | UpgradeLog*.htm 260 | ServiceFabricBackup/ 261 | *.rptproj.bak 262 | 263 | # SQL Server files 264 | *.mdf 265 | *.ldf 266 | *.ndf 267 | 268 | # Business Intelligence projects 269 | *.rdl.data 270 | *.bim.layout 271 | *.bim_*.settings 272 | *.rptproj.rsuser 273 | *- [Bb]ackup.rdl 274 | *- [Bb]ackup ([0-9]).rdl 275 | *- [Bb]ackup ([0-9][0-9]).rdl 276 | 277 | # Microsoft Fakes 278 | FakesAssemblies/ 279 | 280 | # GhostDoc plugin setting file 281 | *.GhostDoc.xml 282 | 283 | # Node.js Tools for Visual Studio 284 | .ntvs_analysis.dat 285 | node_modules/ 286 | 287 | # Visual Studio 6 build log 288 | *.plg 289 | 290 | # Visual Studio 6 workspace options file 291 | *.opt 292 | 293 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 294 | *.vbw 295 | 296 | # Visual Studio LightSwitch build output 297 | **/*.HTMLClient/GeneratedArtifacts 298 | **/*.DesktopClient/GeneratedArtifacts 299 | **/*.DesktopClient/ModelManifest.xml 300 | **/*.Server/GeneratedArtifacts 301 | **/*.Server/ModelManifest.xml 302 | _Pvt_Extensions 303 | 304 | # Paket dependency manager 305 | .paket/paket.exe 306 | paket-files/ 307 | 308 | # FAKE - F# Make 309 | .fake/ 310 | 311 | # CodeRush personal settings 312 | .cr/personal 313 | 314 | # Python Tools for Visual Studio (PTVS) 315 | __pycache__/ 316 | *.pyc 317 | 318 | # Cake - Uncomment if you are using it 319 | # tools/** 320 | # !tools/packages.config 321 | 322 | # Tabs Studio 323 | *.tss 324 | 325 | # Telerik's JustMock configuration file 326 | *.jmconfig 327 | 328 | # BizTalk build output 329 | *.btp.cs 330 | *.btm.cs 331 | *.odx.cs 332 | *.xsd.cs 333 | 334 | # OpenCover UI analysis results 335 | OpenCover/ 336 | 337 | # Azure Stream Analytics local run output 338 | ASALocalRun/ 339 | 340 | # MSBuild Binary and Structured Log 341 | *.binlog 342 | 343 | # NVidia Nsight GPU debugger configuration file 344 | *.nvuser 345 | 346 | # MFractors (Xamarin productivity tool) working folder 347 | .mfractor/ 348 | 349 | # Local History for Visual Studio 350 | .localhistory/ 351 | 352 | # BeatPulse healthcheck temp database 353 | healthchecksdb 354 | 355 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 356 | MigrationBackup/ 357 | 358 | # Ionide (cross platform F# VS Code tools) working folder 359 | .ionide/ 360 | 361 | # Fody - auto-generated XML schema 362 | FodyWeavers.xsd -------------------------------------------------------------------------------- /Beat-360fyer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29230.47 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Beat-360fyer", "./Beat-360fyer/Beat-360fyer.csproj", "{5177250D-F5BB-4F36-A68D-F4F0281993A6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5177250D-F5BB-4F36-A68D-F4F0281993A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {5177250D-F5BB-4F36-A68D-F4F0281993A6}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {5177250D-F5BB-4F36-A68D-F4F0281993A6}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {5177250D-F5BB-4F36-A68D-F4F0281993A6}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {69EBD213-2843-4FEC-9320-551E1DB69EE9} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Beat-360fyer/360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Beat-360fyer/360.png -------------------------------------------------------------------------------- /Beat-360fyer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Beat-360fyer/Beat-360fyer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5177250D-F5BB-4F36-A68D-F4F0281993A6} 8 | WinExe 9 | Stx.ThreeSixtyfyer 10 | Beat-360fyer 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | Everaldo-Starwars-Darth-Mauls-light-sabers.ico 37 | 38 | 39 | 40 | packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll 41 | 42 | 43 | packages\Ookii.Dialogs.1.0\lib\net35\Ookii.Dialogs.Wpf.dll 44 | 45 | 46 | 47 | ..\packages\Semver.2.0.6\lib\net452\Semver.dll 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Form 72 | 73 | 74 | FormGeneratePack.cs 75 | 76 | 77 | Form 78 | 79 | 80 | FormGeneratorSettings.cs 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | FormGeneratePack.cs 95 | 96 | 97 | FormGeneratorSettings.cs 98 | 99 | 100 | ResXFileCodeGenerator 101 | Resources.Designer.cs 102 | Designer 103 | 104 | 105 | True 106 | Resources.resx 107 | True 108 | 109 | 110 | 111 | SettingsSingleFileGenerator 112 | Settings.Designer.cs 113 | 114 | 115 | True 116 | Settings.settings 117 | True 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Beat-360fyer/BeatMap.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Stx.ThreeSixtyfyer 9 | { 10 | public enum RotationEvent 11 | { 12 | Event15 = 15, 13 | Event14 = 14 14 | } 15 | 16 | [Serializable] 17 | public class BeatMap 18 | { 19 | [JsonProperty("_version")] 20 | public string version; 21 | [JsonProperty("_events")] 22 | public List events; 23 | [JsonProperty("_notes")] 24 | public List notes; 25 | [JsonProperty("_obstacles")] 26 | public List obstacles; 27 | [JsonProperty("_customData", DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public object customData; 29 | 30 | public BeatMap() { } 31 | 32 | public BeatMap(BeatMap other) 33 | { 34 | version = other.version; 35 | events = new List(other.events/*.OrderBy((e) => e.time)*/); 36 | notes = new List(other.notes/*.OrderBy((e) => e.time)*/); 37 | obstacles = new List(other.obstacles/*.OrderBy((e) => e.time)*/); 38 | customData = other.customData; 39 | } 40 | 41 | public void AddGoLeftEvent(float time, int steps, RotationEvent mode = RotationEvent.Event15) 42 | { 43 | if (steps == 0) 44 | return; 45 | 46 | events.Add(new BeatMapEvent() 47 | { 48 | time = time, 49 | type = (int)mode, 50 | value = 4 - steps 51 | }); 52 | } 53 | 54 | public void AddGoRightEvent(float time, int steps, RotationEvent mode = RotationEvent.Event15) 55 | { 56 | if (steps == 0) 57 | return; 58 | 59 | events.Add(new BeatMapEvent() 60 | { 61 | time = time, 62 | type = (int)mode, 63 | value = 3 + steps 64 | }); 65 | } 66 | 67 | public void AddWall(float time, int lineIndex, float duration = 1f, int width = 1) 68 | { 69 | obstacles.Add(new BeatMapObstacle() 70 | { 71 | time = time, 72 | duration = duration, 73 | lineIndex = lineIndex, 74 | type = 0, 75 | width = width 76 | }); 77 | } 78 | 79 | public void Sort() 80 | { 81 | events = events.OrderBy((e) => e.time).ToList(); 82 | notes = notes.OrderBy((e) => e.time).ToList(); 83 | obstacles = obstacles.OrderBy((e) => e.time).ToList(); 84 | } 85 | } 86 | 87 | [Serializable] 88 | public class BeatMapEvent 89 | { 90 | [JsonProperty("_time")] 91 | public float time; 92 | [JsonProperty("_type")] 93 | public int type; 94 | [JsonProperty("_value")] 95 | public int value; 96 | } 97 | 98 | [Serializable] 99 | public class BeatMapNote 100 | { 101 | [JsonProperty("_time")] 102 | public float time; 103 | [JsonProperty("_lineIndex")] 104 | public int lineIndex; 105 | [JsonProperty("_lineLayer")] 106 | public int lineLayer; 107 | [JsonProperty("_type")] 108 | public int type; 109 | [JsonProperty("_cutDirection")] 110 | public int cutDirection; 111 | 112 | public override string ToString() 113 | { 114 | return $"Note at {time} type {type}"; 115 | } 116 | } 117 | 118 | [Serializable] 119 | public class BeatMapObstacle 120 | { 121 | [JsonProperty("_time")] 122 | public float time; 123 | [JsonProperty("_duration")] 124 | public float duration; 125 | [JsonProperty("_type")] 126 | public int type; 127 | [JsonProperty("_lineIndex")] 128 | public int lineIndex; 129 | [JsonProperty("_width")] 130 | public int width; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Beat-360fyer/BeatMapGenerator.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Stx.ThreeSixtyfyer.Generators; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Stx.ThreeSixtyfyer 12 | { 13 | public static class BeatMapGenerator 14 | { 15 | public static string ContributorImagePath { get; set; } = null; 16 | public const string GENERATOR_CONFIG_NAME = "Generator.dat"; 17 | 18 | public static IBeatMapGenerator DefaultGenerator => new BeatMap360Generator(); 19 | 20 | public static IEnumerable GeneratorTypes => AppDomain.CurrentDomain.GetAssemblies() 21 | .SelectMany(s => s.GetTypes()) 22 | .Where(p => typeof(IBeatMapGenerator).IsAssignableFrom(p) && !p.IsInterface); 23 | 24 | public static BeatMapGeneratorAttribute GetGeneratorInfo(Type generatorType) 25 | { 26 | var l = generatorType.GetCustomAttributes(typeof(BeatMapGeneratorAttribute), false); 27 | if (l.Length == 0) 28 | return null; 29 | return (BeatMapGeneratorAttribute)l[0]; 30 | } 31 | 32 | public static IBeatMapGenerator GetGeneratorWithName(string name) 33 | { 34 | foreach(Type t in GeneratorTypes) 35 | { 36 | var l = t.GetCustomAttributes(typeof(BeatMapGeneratorAttribute), false); 37 | if (l.Length == 0) 38 | continue; 39 | if (((BeatMapGeneratorAttribute)l[0]).Name == name) 40 | return (IBeatMapGenerator)Activator.CreateInstance(t); 41 | } 42 | 43 | return null; 44 | } 45 | 46 | public struct Result 47 | { 48 | public byte generatedCount; 49 | public bool alreadyUpToDate; 50 | } 51 | 52 | public static Result UseGeneratorAndOverwrite(IBeatMapGenerator generator, BeatMapInfo info, IReadOnlyCollection difficultyLevels, bool forceGenerate = false) 53 | { 54 | info = info.Clone(); 55 | var generatorInfo = generator.GetInformation(); 56 | Result result = new Result(); 57 | HashSet difficulties = new HashSet(difficultyLevels); 58 | info.CreateBackup(); 59 | 60 | bool saveNewInfo = true; 61 | string generatorConfigFile = Path.Combine(info.mapDirectoryPath, GENERATOR_CONFIG_NAME); 62 | if (File.Exists(generatorConfigFile)) 63 | { 64 | BeatMapGeneratorConfig generatorConfig = BeatMapGeneratorConfig.FromFile(generatorConfigFile); 65 | 66 | saveNewInfo = generatorConfig.ShouldSaveInfo(difficulties); 67 | if (!saveNewInfo && !forceGenerate && !generatorConfig.ShouldRegenerate(generator.Settings, generatorInfo.Name, generatorInfo.Version)) 68 | { 69 | result.alreadyUpToDate = true; 70 | return result; // Already up to date! 71 | } 72 | 73 | difficulties.AddRange(generatorConfig.difficulties); 74 | } 75 | 76 | foreach(BeatMapDifficultyLevel difficulty in difficulties) 77 | { 78 | BeatMapDifficulty standardDiff = info.GetGameModeDifficulty(difficulty, "Standard"); 79 | if (standardDiff == null) 80 | continue; 81 | 82 | BeatMapDifficulty newDiff = BeatMapDifficulty.CopyFrom(standardDiff, generator.GeneratedGameModeName); 83 | if (!info.AddGameModeDifficulty(newDiff, generator.GeneratedGameModeName, true)) 84 | continue; 85 | 86 | newDiff.SaveBeatMap(info.mapDirectoryPath, generator.FromStandard(standardDiff.LoadBeatMap(info.mapDirectoryPath), info.beatsPerMinute, info.songTimeOffset)); 87 | result.generatedCount++; 88 | } 89 | if (result.generatedCount == 0) 90 | return result; 91 | 92 | if (saveNewInfo) 93 | { 94 | info.AddContributor(generatorInfo.Name, generator.GeneratedGameModeName, ContributorImagePath); 95 | info.SaveToFile(info.mapInfoPath); 96 | } 97 | 98 | BeatMapGeneratorConfig.FromGenerator(generator, difficulties).SaveToFile(Path.Combine(info.mapDirectoryPath, GENERATOR_CONFIG_NAME)); 99 | return result; 100 | } 101 | 102 | public static Result UseGeneratorAndCopy(IBeatMapGenerator generator, BeatMapInfo info, IReadOnlyCollection difficultyLevels, string destination, bool forceGenerate = false) 103 | { 104 | info = info.Clone(); 105 | var generatorInfo = generator.GetInformation(); 106 | Result result = new Result(); 107 | HashSet difficulties = new HashSet(difficultyLevels); 108 | string mapDestination = Path.Combine(destination, new DirectoryInfo(info.mapDirectoryPath).Name); 109 | 110 | bool saveNewInfo = true; 111 | string generatorConfigFile = Path.Combine(mapDestination, GENERATOR_CONFIG_NAME); 112 | if (File.Exists(generatorConfigFile)) 113 | { 114 | BeatMapGeneratorConfig generatorConfig = BeatMapGeneratorConfig.FromFile(generatorConfigFile); 115 | 116 | saveNewInfo = generatorConfig.ShouldSaveInfo(difficulties); 117 | if (!saveNewInfo && !forceGenerate && !generatorConfig.ShouldRegenerate(generator.Settings, generatorInfo.Name, generatorInfo.Version)) 118 | { 119 | result.alreadyUpToDate = true; 120 | return result; // Already up to date! 121 | } 122 | 123 | difficulties.AddRange(generatorConfig.difficulties); 124 | } 125 | 126 | Directory.CreateDirectory(mapDestination); 127 | 128 | foreach (BeatMapDifficultyLevel difficulty in difficulties) 129 | { 130 | BeatMapDifficulty standardDiff = info.GetGameModeDifficulty(difficulty, "Standard"); 131 | if (standardDiff == null) 132 | continue; 133 | 134 | BeatMapDifficulty newDiff = BeatMapDifficulty.CopyFrom(standardDiff, generator.GeneratedGameModeName); 135 | if (!info.AddGameModeDifficulty(newDiff, generator.GeneratedGameModeName, true)) // always replace when making a copy 136 | continue; 137 | 138 | newDiff.SaveBeatMap(mapDestination, generator.FromStandard(standardDiff.LoadBeatMap(info.mapDirectoryPath), info.beatsPerMinute, info.songTimeOffset)); 139 | result.generatedCount++; 140 | } 141 | if (result.generatedCount == 0) 142 | return result; 143 | 144 | info.difficultyBeatmapSets.RemoveAll((diffSet) => diffSet.beatmapCharacteristicName != generator.GeneratedGameModeName); 145 | 146 | if (saveNewInfo) 147 | { 148 | string coverImagePath = Path.Combine(info.mapDirectoryPath, info.coverImageFilename); // There are some songs without cover images 149 | if (File.Exists(coverImagePath)) 150 | File.Copy(coverImagePath, Path.Combine(mapDestination, info.coverImageFilename), true); 151 | File.Copy(Path.Combine(info.mapDirectoryPath, info.songFilename), Path.Combine(mapDestination, info.songFilename), true); 152 | info.AddContributor(generatorInfo.Name, generator.GeneratedGameModeName, ContributorImagePath); 153 | info.SaveToFile(Path.Combine(mapDestination, "Info.dat")); 154 | } 155 | 156 | BeatMapGeneratorConfig.FromGenerator(generator, difficulties).SaveToFile(Path.Combine(mapDestination, GENERATOR_CONFIG_NAME)); 157 | return result; 158 | } 159 | 160 | public static bool IsDefaultSettings(object settings) 161 | { 162 | if (settings == null) 163 | return false; 164 | 165 | return Activator.CreateInstance(settings.GetType()).Equals(settings); 166 | } 167 | } 168 | 169 | public static class BeatMapGeneratorExtensions 170 | { 171 | public static BeatMapGeneratorAttribute GetInformation(this IBeatMapGenerator generator) 172 | { 173 | return BeatMapGenerator.GetGeneratorInfo(generator.GetType()); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Beat-360fyer/BeatMapGeneratorAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Stx.ThreeSixtyfyer 4 | { 5 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 6 | public class BeatMapGeneratorAttribute : Attribute 7 | { 8 | public int Version { get; } 9 | public string Name { get; } 10 | public string Author { get; } 11 | public string Description { get; } 12 | 13 | public BeatMapGeneratorAttribute(string generatorName, int generatorVersion, string author, string description) 14 | { 15 | Version = generatorVersion; 16 | Name = generatorName; 17 | Author = author; 18 | Description = description; 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Beat-360fyer/BeatMapGeneratorConfig.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | 6 | namespace Stx.ThreeSixtyfyer 7 | { 8 | [Serializable] 9 | public class BeatMapGeneratorConfig 10 | { 11 | [JsonProperty("_configVersion")] 12 | public int configVersion = 1; 13 | [JsonProperty("_generatorSettings")] 14 | public object generatorSettings; 15 | [JsonProperty("_generatorVersion")] 16 | public int generatorVersion; 17 | [JsonProperty("_generatorName")] 18 | public string generatorName; 19 | [JsonProperty("_difficulties")] 20 | public HashSet difficulties; 21 | 22 | public bool ShouldRegenerate(object newSettings, string newGeneratorName, int newGeneratorVersion) 23 | { 24 | if (generatorName != newGeneratorName) 25 | return true; 26 | if (newGeneratorVersion > generatorVersion) 27 | return true; 28 | if (!generatorSettings.Equals(newSettings)) 29 | return true; 30 | return false; 31 | } 32 | 33 | public bool ShouldSaveInfo(HashSet newDifficulties) 34 | { 35 | return !HasDifficulties(newDifficulties); 36 | } 37 | 38 | public static BeatMapGeneratorConfig FromGenerator(IBeatMapGenerator generator, HashSet difficulties) 39 | { 40 | var info = generator.GetInformation(); 41 | return new BeatMapGeneratorConfig() 42 | { 43 | generatorSettings = generator.Settings, 44 | generatorVersion = info.Version, 45 | generatorName = info.Name, 46 | difficulties = difficulties 47 | }; 48 | } 49 | 50 | public void SaveToFile(string file) 51 | { 52 | File.WriteAllText(file, JsonConvert.SerializeObject(this, Program.JsonSettings)); 53 | } 54 | 55 | public bool HasDifficulties(IReadOnlyCollection all) 56 | { 57 | foreach (BeatMapDifficultyLevel diff in all) 58 | { 59 | if (!difficulties.Contains(diff)) 60 | return false; 61 | } 62 | return true; 63 | } 64 | 65 | public static BeatMapGeneratorConfig FromFile(string file) 66 | { 67 | return JsonConvert.DeserializeObject(File.ReadAllText(file), Program.JsonSettings); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Beat-360fyer/BeatMapInfo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Stx.ThreeSixtyfyer.Generators; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Stx.ThreeSixtyfyer 11 | { 12 | public enum BeatMapDifficultyLevel 13 | { 14 | Easy = 1, 15 | Normal = 3, 16 | Hard = 5, 17 | Expert = 7, 18 | ExpertPlus = 9 19 | } 20 | 21 | [Serializable] 22 | public class BeatMapInfo : ICloneable 23 | { 24 | [JsonProperty("_version")] 25 | public string version; 26 | [JsonProperty("_songName")] 27 | public string songName; 28 | [JsonProperty("_songSubName")] 29 | public string songSubName; 30 | [JsonProperty("_songAuthorName")] 31 | public string songAuthorName; 32 | [JsonProperty("_levelAuthorName")] 33 | public string levelAuthorName; 34 | [JsonProperty("_beatsPerMinute")] 35 | public float beatsPerMinute; 36 | [JsonProperty("_songTimeOffset")] 37 | public float songTimeOffset; 38 | [JsonProperty("_shuffle")] 39 | public float shuffle; 40 | [JsonProperty("_shufflePeriod")] 41 | public float shufflePeriod; 42 | [JsonProperty("_previewStartTime")] 43 | public float previewStartTime; 44 | [JsonProperty("_previewDuration")] 45 | public float previewDuration; 46 | [JsonProperty("_songFilename")] 47 | public string songFilename; 48 | [JsonProperty("_coverImageFilename")] 49 | public string coverImageFilename; 50 | [JsonProperty("_environmentName")] 51 | public string environmentName; 52 | [JsonProperty("_allDirectionsEnvironmentName")] 53 | public string allDirectionsEnvironmentName; 54 | [JsonProperty("_difficultyBeatmapSets")] 55 | public List difficultyBeatmapSets; 56 | [JsonProperty("_customData", DefaultValueHandling = DefaultValueHandling.Ignore)] 57 | public BeatMapInfoCustomData customData; 58 | 59 | [JsonIgnore] 60 | public string mapDirectoryPath; 61 | [JsonIgnore] 62 | public string mapInfoPath; 63 | 64 | public static BeatMapInfo FromFile(string absoluteInfoFilePath) 65 | { 66 | BeatMapInfo info = JsonConvert.DeserializeObject(File.ReadAllText(absoluteInfoFilePath), Program.JsonSettings); 67 | info.mapInfoPath = absoluteInfoFilePath; 68 | info.mapDirectoryPath = new FileInfo(absoluteInfoFilePath).Directory.FullName; 69 | return info; 70 | } 71 | 72 | public void SaveToFile(string file) 73 | { 74 | File.WriteAllText(file, JsonConvert.SerializeObject(this, Program.JsonSettings)); 75 | } 76 | 77 | public void CreateBackup(bool overwrite = false) 78 | { 79 | string backupFile = Path.Combine(mapDirectoryPath, "Info.dat.bak"); 80 | if (overwrite || !File.Exists(backupFile)) 81 | File.Copy(mapInfoPath, backupFile, true); 82 | } 83 | 84 | public BeatMapDifficultySet GetGameMode(string gameMode) 85 | { 86 | return difficultyBeatmapSets.FirstOrDefault((difs) => difs.beatmapCharacteristicName == gameMode); 87 | } 88 | 89 | public BeatMapDifficulty GetGameModeDifficulty(BeatMapDifficultyLevel difficulty, string gameMode) 90 | { 91 | BeatMapDifficultySet diffSet = GetGameMode(gameMode); 92 | return diffSet?.difficultyBeatmaps.FirstOrDefault((diff) => diff.difficulty == difficulty.ToString()); 93 | } 94 | 95 | public bool RemoveGameModeDifficulty(BeatMapDifficultyLevel difficulty, string gameMode) 96 | { 97 | BeatMapDifficultySet diffSet = GetGameMode(gameMode); 98 | 99 | if (diffSet == null) 100 | return false; // it is already removed 101 | 102 | bool res = diffSet.difficultyBeatmaps.RemoveAll((diff) => diff.difficulty == difficulty.ToString()) > 0; 103 | 104 | if (diffSet.difficultyBeatmaps.Count == 0) // remove gamemode if all difficulties are removed 105 | difficultyBeatmapSets.RemoveAll((diff) => diff.beatmapCharacteristicName == gameMode); 106 | 107 | return res; 108 | } 109 | 110 | public bool AddGameModeDifficulty(BeatMapDifficulty newDifficulty, string gameMode, bool replaceExisting) 111 | { 112 | BeatMapDifficultySet newDiffSet = difficultyBeatmapSets.FirstOrDefault((difs) => difs.beatmapCharacteristicName == gameMode); 113 | if (newDiffSet == null) 114 | { 115 | newDiffSet = new BeatMapDifficultySet() 116 | { 117 | beatmapCharacteristicName = gameMode, 118 | difficultyBeatmaps = new List() 119 | }; 120 | difficultyBeatmapSets.Add(newDiffSet); 121 | } 122 | 123 | BeatMapDifficulty existingDiff = newDiffSet.difficultyBeatmaps.FirstOrDefault((diff) => diff.difficulty == newDifficulty.difficulty.ToString()); 124 | if (existingDiff != null) 125 | { 126 | if (!replaceExisting) 127 | return false; 128 | 129 | newDiffSet.difficultyBeatmaps.Remove(existingDiff); 130 | } 131 | 132 | newDiffSet.difficultyBeatmaps.Add(newDifficulty); 133 | newDiffSet.difficultyBeatmaps = newDiffSet.difficultyBeatmaps.OrderBy((diff) => diff.difficultyRank).ToList(); 134 | return true; 135 | } 136 | 137 | public void AddContributor(string name, string role, string iconPath = "") 138 | { 139 | if (customData.contributors == null) 140 | customData.contributors = new List(); 141 | if (!customData.contributors.Any((cont) => cont.name == name)) 142 | customData.contributors.Add(new BeatMapContributor() 143 | { 144 | name = name, 145 | role = role, 146 | iconPath = iconPath 147 | }); 148 | } 149 | 150 | public override string ToString() 151 | { 152 | return string.IsNullOrEmpty(songAuthorName) ? songName : $"{songName} - {songAuthorName}"; 153 | } 154 | 155 | public BeatMapInfo Clone() 156 | { 157 | return new BeatMapInfo() 158 | { 159 | version = version, 160 | songName = songName, 161 | songSubName = songSubName, 162 | songAuthorName = songAuthorName, 163 | levelAuthorName = levelAuthorName, 164 | beatsPerMinute = beatsPerMinute, 165 | songTimeOffset = songTimeOffset, 166 | shuffle = shuffle, 167 | shufflePeriod = shufflePeriod, 168 | previewStartTime = previewStartTime, 169 | previewDuration = previewDuration, 170 | songFilename = songFilename, 171 | coverImageFilename = coverImageFilename, 172 | environmentName = environmentName, 173 | allDirectionsEnvironmentName = allDirectionsEnvironmentName, 174 | difficultyBeatmapSets = new List(difficultyBeatmapSets.Clone()), 175 | customData = customData, 176 | mapDirectoryPath = mapDirectoryPath, 177 | mapInfoPath = mapInfoPath 178 | }; 179 | } 180 | } 181 | 182 | [Serializable] 183 | public struct BeatMapInfoCustomData 184 | { 185 | [JsonProperty("_customEnvironment", DefaultValueHandling = DefaultValueHandling.Ignore)] 186 | public string customEnvironment; 187 | [JsonProperty("_customEnvironmentHash", DefaultValueHandling = DefaultValueHandling.Ignore)] 188 | public string customEnvironmentHash; 189 | [JsonProperty("_contributors", DefaultValueHandling = DefaultValueHandling.Ignore)] 190 | public List contributors; 191 | } 192 | 193 | [Serializable] 194 | public struct BeatMapContributor 195 | { 196 | [JsonProperty("_role")] 197 | public string role; 198 | [JsonProperty("_name")] 199 | public string name; 200 | [JsonProperty("_iconPath")] 201 | public string iconPath; 202 | } 203 | 204 | [Serializable] 205 | public class BeatMapDifficultySet : ICloneable 206 | { 207 | [JsonProperty("_beatmapCharacteristicName")] 208 | public string beatmapCharacteristicName; 209 | [JsonProperty("_difficultyBeatmaps")] 210 | public List difficultyBeatmaps; 211 | 212 | public BeatMapDifficultySet Clone() 213 | { 214 | return new BeatMapDifficultySet() 215 | { 216 | beatmapCharacteristicName = beatmapCharacteristicName, 217 | difficultyBeatmaps = new List(difficultyBeatmaps.Clone()) 218 | }; 219 | } 220 | } 221 | 222 | [Serializable] 223 | public class BeatMapDifficulty : ICloneable 224 | { 225 | [JsonProperty("_difficulty")] 226 | public string difficulty; 227 | [JsonProperty("_difficultyRank")] 228 | public int difficultyRank; 229 | [JsonProperty("_beatmapFilename")] 230 | public string beatmapFilename; 231 | [JsonProperty("_noteJumpMovementSpeed")] 232 | public float noteJumpMovementSpeed; 233 | [JsonProperty("_noteJumpStartBeatOffset")] 234 | public float noteJumpStartBeatOffset; 235 | [JsonProperty("_customData", DefaultValueHandling = DefaultValueHandling.Ignore)] 236 | public object customData; 237 | 238 | public static IEnumerable AllDiffultyLevels => Enum.GetValues(typeof(BeatMapDifficultyLevel)).Cast(); 239 | 240 | public BeatMap LoadBeatMap(string mapDirectory) 241 | { 242 | string fullPath = Path.Combine(mapDirectory, beatmapFilename); 243 | return JsonConvert.DeserializeObject(File.ReadAllText(fullPath), Program.JsonSettings); 244 | } 245 | 246 | public void SaveBeatMap(string mapDirectory, BeatMap map) 247 | { 248 | string fullPath = Path.Combine(mapDirectory, beatmapFilename); 249 | File.WriteAllText(fullPath, JsonConvert.SerializeObject(map, Program.JsonSettings)); 250 | } 251 | 252 | public static BeatMapDifficulty Create(BeatMapDifficultyLevel difficulty, string gameMode) 253 | { 254 | return new BeatMapDifficulty() 255 | { 256 | difficulty = difficulty.ToString(), 257 | difficultyRank = (int)difficulty, 258 | beatmapFilename = gameMode + difficulty.ToString() + ".dat", 259 | noteJumpMovementSpeed = 0.0f, 260 | noteJumpStartBeatOffset = 0.0f 261 | }; 262 | } 263 | 264 | public static BeatMapDifficulty CopyFrom(BeatMapDifficulty difficulty, string gameMode = "") 265 | { 266 | return new BeatMapDifficulty() 267 | { 268 | difficulty = difficulty.difficulty, 269 | difficultyRank = difficulty.difficultyRank, 270 | beatmapFilename = gameMode + difficulty.difficulty + ".dat", 271 | noteJumpMovementSpeed = difficulty.noteJumpMovementSpeed, 272 | noteJumpStartBeatOffset = difficulty.noteJumpStartBeatOffset, 273 | customData = difficulty.customData 274 | }; 275 | } 276 | 277 | public BeatMapDifficulty Clone() 278 | { 279 | return new BeatMapDifficulty() 280 | { 281 | difficulty = difficulty, 282 | difficultyRank = difficultyRank, 283 | beatmapFilename = beatmapFilename, 284 | noteJumpMovementSpeed = noteJumpMovementSpeed, 285 | noteJumpStartBeatOffset = noteJumpStartBeatOffset, 286 | customData = customData 287 | }; 288 | } 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /Beat-360fyer/Config.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | 4 | namespace Stx.ThreeSixtyfyer 5 | { 6 | public abstract class Config 7 | { 8 | public const string CONFIG_FILENAME = "config.json"; 9 | 10 | [JsonProperty("version")] 11 | public abstract int Version { get; } 12 | 13 | protected Config() { } 14 | 15 | public static TConfig Load() where TConfig : Config, new() 16 | { 17 | TConfig n = new TConfig(); 18 | if (!File.Exists(CONFIG_FILENAME)) 19 | { 20 | return n; 21 | } 22 | else 23 | { 24 | TConfig c = JsonConvert.DeserializeObject(File.ReadAllText(CONFIG_FILENAME), Program.JsonSettings); 25 | if (c.Version < n.Version) 26 | c = (TConfig)n.Upgrade(c, c.Version); 27 | return c; 28 | } 29 | } 30 | 31 | public void Save() 32 | { 33 | File.WriteAllText(CONFIG_FILENAME, JsonConvert.SerializeObject(this, Program.JsonSettings)); 34 | } 35 | 36 | public static bool TryLoad(out TConfig config) where TConfig : Config, new() 37 | { 38 | try 39 | { 40 | config = Load(); 41 | return true; 42 | } 43 | catch 44 | { 45 | config = null; 46 | return false; 47 | } 48 | } 49 | 50 | public bool TrySave() 51 | { 52 | try 53 | { 54 | Save(); 55 | return true; 56 | } 57 | catch 58 | { 59 | return false; 60 | } 61 | } 62 | 63 | public virtual Config Upgrade(dynamic oldConfig, int oldConfigVersion) 64 | { 65 | return oldConfig; 66 | } 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Beat-360fyer/Everaldo-Starwars-Darth-Mauls-light-sabers.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Beat-360fyer/Everaldo-Starwars-Darth-Mauls-light-sabers.ico -------------------------------------------------------------------------------- /Beat-360fyer/FileEnumerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Stx.ThreeSixtyfyer 9 | { 10 | public class FileEnumerator 11 | { 12 | public static IEnumerable GetFilesRecursive(string root, string searchPattern) 13 | { 14 | string[] files = Directory.GetFiles(root, searchPattern, SearchOption.TopDirectoryOnly); 15 | 16 | if (files.Length == 0) 17 | yield return null; 18 | foreach (string file in files) 19 | yield return file; 20 | 21 | foreach (string dir in Directory.GetDirectories(root)) 22 | foreach (string file in GetFilesRecursive(dir, searchPattern)) 23 | yield return file; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Beat-360fyer/FormGeneratePack.cs: -------------------------------------------------------------------------------- 1 | using Ookii.Dialogs.Wpf; 2 | using Stx.ThreeSixtyfyer.Generators; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Data; 7 | using System.Diagnostics; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Reflection; 12 | using System.Text; 13 | using System.Text.RegularExpressions; 14 | using System.Threading.Tasks; 15 | using System.Windows.Forms; 16 | using System.Xml; 17 | using System.Xml.Linq; 18 | 19 | namespace Stx.ThreeSixtyfyer 20 | { 21 | public partial class FormGeneratePack : Form 22 | { 23 | private IBeatMapGenerator generator; 24 | private ThreeSixtyfyerConfig config; 25 | private bool updateMusicPackOnStart = false; 26 | private bool beatSaberAvailable = false; 27 | private bool songCoreAvailable = false; 28 | 29 | private string CustomSongsPath => beatSaberAvailable ? Path.Combine(textBoxBeatSaberPath.Text, "Beat Saber_Data", "CustomLevels") : textBoxBeatSaberPath.Text; 30 | 31 | public FormGeneratePack(bool updateMusicPackOnStart = false) 32 | { 33 | InitializeComponent(); 34 | 35 | this.updateMusicPackOnStart = updateMusicPackOnStart; 36 | } 37 | 38 | private void ButtonSelectBeatSaber_Click(object sender, EventArgs e) 39 | { 40 | VistaFolderBrowserDialog folderBrowser = new VistaFolderBrowserDialog() 41 | { 42 | SelectedPath = config.packPath, 43 | Description = "Please select the directory containing 'Beat Saber.exe' to create a music pack. Or open any other directory that contains songs to export or modify.", 44 | ShowNewFolderButton = false, 45 | UseDescriptionForTitle = false 46 | }; 47 | 48 | if (!(folderBrowser.ShowDialog() ?? false)) 49 | return; 50 | 51 | SetBeatSaberPath(folderBrowser.SelectedPath); 52 | } 53 | 54 | private void SetBeatSaberPath(string path) 55 | { 56 | beatSaberAvailable = File.Exists(Path.Combine(path, "Beat Saber.exe")); 57 | songCoreAvailable = beatSaberAvailable && File.Exists(Path.Combine(path, "UserData", "SongCore", "folders.xml")); 58 | 59 | bool enablePack = beatSaberAvailable && songCoreAvailable; 60 | radioButtonMusicPack.Enabled = enablePack; 61 | panelMusicPack.Enabled = enablePack; 62 | if (!enablePack) 63 | radioButtonExport.PerformClick(); 64 | 65 | if (!beatSaberAvailable) 66 | labelBeatSaberStatus.Text = "Beat Saber not found in specfied directory."; 67 | else if (!songCoreAvailable) 68 | labelBeatSaberStatus.Text = "SongCore is not installed (required)."; 69 | else 70 | labelBeatSaberStatus.Text = ""; 71 | 72 | config.packPath = path; 73 | 74 | textBoxBeatSaberPath.Text = path; 75 | this.Height = 741; 76 | 77 | RefreshSongs(); 78 | } 79 | 80 | private void RefreshSongs() 81 | { 82 | listSongs.Items.Clear(); 83 | 84 | Jobs.FindSongsUnderPath(CustomSongsPath, (job) => 85 | { 86 | listSongs.Items.AddRange(job.result.beatMaps.Select((bm) => 87 | new ListViewItem(new string[] { bm.songName, bm.songAuthorName }) { 88 | Text = bm.songName, 89 | Group = listSongs.Groups[0], 90 | Tag = bm 91 | }).ToArray()); 92 | 93 | foreach (ListViewItem item in listSongs.Items) 94 | { 95 | item.Checked = true; 96 | item.Selected = true; 97 | } 98 | }); 99 | } 100 | 101 | private void EnsureCustomPack(string name, string songsDir, string imagePath) 102 | { 103 | Directory.CreateDirectory(songsDir); 104 | 105 | string foldersFile = Path.Combine(textBoxBeatSaberPath.Text, "UserData", "SongCore", "folders.xml"); 106 | XDocument document = XDocument.Load(foldersFile); 107 | 108 | // Remove old pack entry 109 | foreach (var folder in document.Root.Descendants("folder")) 110 | { 111 | if (folder.Element("Name").Value == name || folder.Element("Path").Value == songsDir) 112 | { 113 | folder.Remove(); 114 | break; 115 | } 116 | } 117 | 118 | document.Root.Add( 119 | new XElement("folder", 120 | new XElement("Name", name), 121 | new XElement("Path", songsDir), 122 | new XElement("Pack", 2), 123 | new XElement("ImagePath", imagePath))); 124 | 125 | document.Save(foldersFile); 126 | } 127 | 128 | private void SetUI(bool enabled) 129 | { 130 | this.Enabled = enabled; 131 | } 132 | 133 | private void ListSongs_KeyDown(object sender, KeyEventArgs e) 134 | { 135 | if (e.Control && e.KeyCode == Keys.A) 136 | { 137 | foreach (ListViewItem item in listSongs.Items) 138 | { 139 | item.Checked = true; 140 | item.Selected = true; 141 | } 142 | } 143 | else if (e.Control && e.KeyCode == Keys.D) 144 | { 145 | foreach (ListViewItem item in listSongs.Items) 146 | { 147 | item.Checked = false; 148 | item.Selected = false; 149 | } 150 | } 151 | } 152 | 153 | private void FormGenerate_Load(object sender, EventArgs e) 154 | { 155 | this.Height = 165; 156 | 157 | GitHubBasedUpdateCheck updateChecker = new GitHubBasedUpdateCheck("CodeStix", "Beat-360fyer", "Build/latestVersion.txt"); 158 | updateChecker.CheckForUpdate(Assembly.GetExecutingAssembly().GetName().Version.ToString(3)).ContinueWith((update) => { 159 | 160 | if (update.Result && MessageBox.Show("There is an update available for Beat-360fyer, please download the newest version " + 161 | "to receive new generator features and improvements. Go to the download page right now?", "An update!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) 162 | { 163 | Process.Start(@"https://github.com/CodeStix/Beat-360fyer/releases"); 164 | Environment.Exit(0); 165 | } 166 | }); 167 | 168 | if (!Config.TryLoad(out config)) 169 | { 170 | MessageBox.Show("Could not load the config file, no permission? Maybe run as administrator?", "Could not load config.", MessageBoxButtons.OK, MessageBoxIcon.Error); 171 | } 172 | 173 | generator = BeatMapGenerator.GetGeneratorWithName(config.generatorToUse); 174 | if (generator == null) 175 | { 176 | MessageBox.Show($"Generator with name {config.generatorToUse} not found (found in config file). Setting to default generator.", "Unknown generator.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 177 | generator = BeatMapGenerator.DefaultGenerator; 178 | config.generatorToUse = generator.GetInformation().Name; 179 | } 180 | if (config.generatorSettings.ContainsKey(config.generatorToUse)) 181 | generator.Settings = config.generatorSettings[config.generatorToUse]; 182 | 183 | foreach (Type generatorType in BeatMapGenerator.GeneratorTypes) 184 | comboBoxGenerator.Items.Add(BeatMapGenerator.GetGeneratorInfo(generatorType).Name); 185 | comboBoxGenerator.SelectedItem = config.generatorToUse; 186 | 187 | UpdateGeneratorSettingsButton(); 188 | buttonUpdatePack.Visible = !string.IsNullOrEmpty(config.lastGeneratedMusicPackPath) && !string.IsNullOrEmpty(config.lastGeneratedMusicPackSourcePath); 189 | 190 | if (!string.IsNullOrEmpty(config.packPath)) 191 | SetBeatSaberPath(config.packPath); 192 | 193 | if (updateMusicPackOnStart) 194 | buttonUpdatePack.PerformClick(); 195 | 196 | foreach(BeatMapDifficultyLevel level in BeatMapDifficulty.AllDiffultyLevels) 197 | listDifficulties.Items.Add(level, true); 198 | } 199 | 200 | private void ButtonGenerate_Click(object sender, EventArgs e) 201 | { 202 | try 203 | { 204 | if (radioButtonMusicPack.Checked && beatSaberAvailable && songCoreAvailable) 205 | { 206 | if (textBoxPackName.Text.Length < 1) 207 | throw new Exception($"The pack name '{textBoxPackName.Text}' is too short."); 208 | if (!Regex.IsMatch(textBoxPackName.Text, "^[a-zA-Z0-9-_ ]+$")) 209 | throw new Exception($"The pack name '{textBoxPackName.Text}' contains illegal characters, it should only contain A-Z 0-9 - _ and spaces."); 210 | 211 | string customGeneratedLevelsPath = Path.Combine(textBoxBeatSaberPath.Text, "Beat Saber_Data", "Custom" + textBoxPackName.Text.Replace(" ", "")); 212 | 213 | Directory.CreateDirectory(customGeneratedLevelsPath); 214 | string imagePath = Path.Combine(customGeneratedLevelsPath, "cover.png"); 215 | Properties.Resources.PackThumbnail.Save(imagePath); 216 | BeatMapGenerator.ContributorImagePath = imagePath; 217 | 218 | EnsureCustomPack(textBoxPackName.Text, customGeneratedLevelsPath, imagePath); 219 | 220 | config.lastGeneratedMusicPackSourcePath = CustomSongsPath; 221 | config.lastGeneratedMusicPackPath = customGeneratedLevelsPath; 222 | 223 | ConvertCheckedSongs(customGeneratedLevelsPath); 224 | } 225 | else if (radioButtonExport.Checked) 226 | { 227 | VistaFolderBrowserDialog folderBrowser = new VistaFolderBrowserDialog(); 228 | folderBrowser.SelectedPath = config.exportPath; 229 | folderBrowser.Description = "Select a root directory where all the generated 360 songs should be exported to. Each exported song will be placed in his own directory under this path."; 230 | if (!(folderBrowser.ShowDialog() ?? false)) 231 | return; 232 | 233 | config.lastGeneratedMusicPackSourcePath = CustomSongsPath; 234 | config.lastGeneratedMusicPackPath = folderBrowser.SelectedPath; 235 | 236 | ConvertCheckedSongs(folderBrowser.SelectedPath); 237 | } 238 | else if (radioButtonModify.Checked) 239 | { 240 | if (CustomSongsPath.EndsWith(@"Beat Saber_Data\CustomLevels")) 241 | { 242 | if (MessageBox.Show("Are you sure you want to modify maps directly in your BeatSaber/CustomLevels directory? This will break ScoreSaber submission on the selected maps.\nYou should create a music pack instead.", "Sure?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning) != DialogResult.Yes) 243 | return; 244 | } 245 | 246 | config.lastGeneratedMusicPackSourcePath = null; 247 | config.lastGeneratedMusicPackPath = null; 248 | 249 | ConvertCheckedSongs(null); 250 | } 251 | } 252 | catch (Exception ex) 253 | { 254 | MessageBox.Show($"Cannot start generator: {ex.Message}.\nPlease open a GitHub issue if this is a bug.", "Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); 255 | return; 256 | } 257 | } 258 | 259 | private void ConvertCheckedSongs(string destination) 260 | { 261 | if (listSongs.CheckedItems.Count == 0) 262 | { 263 | MessageBox.Show("You have nothing selected!\n" + 264 | "First, select the songs you want to add the new mode to, then click the generate button.", 265 | "Oops", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 266 | return; 267 | } 268 | else if (listDifficulties.CheckedItems.Count == 0) 269 | { 270 | MessageBox.Show("No difficulties were selected!\n" + 271 | "First, select some difficulties you wish to create a new mode for."); 272 | return; 273 | } 274 | 275 | SetUI(false); 276 | 277 | BeatMapInfo[] maps = new BeatMapInfo[listSongs.CheckedItems.Count]; 278 | for (int i = 0; i < listSongs.CheckedItems.Count; i++) 279 | maps[i] = (BeatMapInfo)listSongs.CheckedItems[i].Tag; 280 | 281 | BeatMapDifficultyLevel[] levels = new BeatMapDifficultyLevel[listDifficulties.CheckedItems.Count]; 282 | listDifficulties.CheckedItems.CopyTo(levels, 0); 283 | 284 | Jobs.GenerateMapsOptions options = new Jobs.GenerateMapsOptions() 285 | { 286 | difficultyLevels = new HashSet(levels), 287 | destination = destination, 288 | toGenerateFor = new List(maps), 289 | forceGenerate = checkBoxForceGenerate.Checked, 290 | generator = generator 291 | }; 292 | 293 | Jobs.GenerateMaps(options, (job) => 294 | { 295 | CreateResultTaskDialog(job, "Generation process complete!").ShowDialog(); 296 | 297 | BeginInvoke(new MethodInvoker(() => SetUI(true))); 298 | }); 299 | } 300 | 301 | private TaskDialog CreateResultTaskDialog(WorkerJob job, string windowTitle) 302 | { 303 | StringBuilder message = new StringBuilder(); 304 | StringBuilder footer = new StringBuilder(); 305 | TaskDialogIcon icon = TaskDialogIcon.Information; 306 | 307 | if (job.result.mapsGenerated == 0) 308 | { 309 | if (job.result.mapsIterated == 0) 310 | { 311 | message.AppendLine("No maps were selected."); 312 | } 313 | else if (job.result.mapsUpToDate > 0) 314 | { 315 | message.AppendLine("All the selected maps are already up to date. If you want to force mode generation, please check 'Force Generate' in the menu."); 316 | } 317 | else 318 | { 319 | message.AppendLine("No modes were added, this can be due to:"); 320 | message.AppendLine(" - The selected songs didn't have the standard mode, this is required for the conversion."); 321 | message.AppendLine(" - Unknown reason..."); 322 | } 323 | icon = TaskDialogIcon.Warning; 324 | } 325 | else if (radioButtonMusicPack.Checked) 326 | { 327 | message.AppendLine($"Done. Navigate to custom levels in the game and a new music pack named '{textBoxPackName.Text}' should appear.\n"); 328 | icon = TaskDialogIcon.Information; 329 | } 330 | else if (radioButtonExport.Checked) 331 | { 332 | message.AppendLine($"Done. The generated levels were exported to '{job.argument.destination}'."); 333 | icon = TaskDialogIcon.Information; 334 | } 335 | else if (radioButtonModify.Checked) 336 | { 337 | message.AppendLine($"Done. The selected levels were modified directly."); 338 | icon = TaskDialogIcon.Information; 339 | } 340 | if (job.result.cancelled) 341 | { 342 | footer.Append("The operation was cancelled. "); 343 | icon = TaskDialogIcon.Warning; 344 | } 345 | if (job.exceptions.Count > 0) 346 | { 347 | footer.Append($"{job.exceptions.Count} problems occured. "); 348 | icon = TaskDialogIcon.Error; 349 | } 350 | else 351 | { 352 | footer.Append($"No problems occured. "); 353 | } 354 | 355 | StringBuilder stats = new StringBuilder(); 356 | stats.AppendLine($"{job.result.mapsIterated} maps iterated."); 357 | stats.AppendLine($"{job.result.mapsGenerated} maps generated."); 358 | stats.AppendLine($"{job.result.difficultiesGenerated} difficulties generated. ({string.Join(", ", job.argument.difficultyLevels)})"); 359 | if (job.result.mapsUpToDate > 0) 360 | stats.AppendLine($"{job.result.mapsUpToDate} maps were already up to date."); 361 | 362 | TaskDialog dialog = new TaskDialog(); 363 | dialog.WindowTitle = windowTitle; 364 | dialog.MainIcon = icon; 365 | dialog.Content = message.ToString(); 366 | dialog.Footer = footer.ToString(); 367 | dialog.ExpandedByDefault = true; 368 | dialog.ExpandedInformation = stats.ToString(); 369 | dialog.Buttons.Add(new TaskDialogButton(ButtonType.Ok)); 370 | if (job.exceptions.Count > 0) 371 | { 372 | dialog.Buttons.Add(new TaskDialogButton("Show problems")); 373 | dialog.ButtonClicked += (sender, e) => 374 | { 375 | if (e.Item.Text == "Show problems") 376 | { 377 | StringBuilder str = new StringBuilder(); 378 | for (int i = 0; i < job.exceptions.Count && i < 10; i++) 379 | str.AppendLine(job.exceptions[i].Message); 380 | if (job.exceptions.Count > 10) 381 | str.AppendLine($"\nAnd {job.exceptions.Count - 10} more..."); 382 | 383 | MessageBox.Show(str.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 384 | } 385 | }; 386 | } 387 | 388 | return dialog; 389 | } 390 | 391 | private void buttonUpdatePack_Click(object sender, EventArgs e) 392 | { 393 | if (string.IsNullOrEmpty(config.lastGeneratedMusicPackPath) || string.IsNullOrEmpty(config.lastGeneratedMusicPackSourcePath)) 394 | { 395 | Console.WriteLine("Update pack button was pressed but nothing to update."); 396 | return; 397 | } 398 | 399 | Jobs.FindSongsUnderPath(config.lastGeneratedMusicPackSourcePath, (findSongsJob) => 400 | { 401 | Jobs.GenerateMaps(new Jobs.GenerateMapsOptions() 402 | { 403 | difficultyLevels = BeatMapDifficulty.AllDiffultyLevels.ToHashSet(), 404 | destination = config.lastGeneratedMusicPackPath, 405 | toGenerateFor = findSongsJob.result.beatMaps, 406 | forceGenerate = checkBoxForceGenerate.Checked, 407 | generator = generator 408 | }, (updateJob) => 409 | { 410 | CreateResultTaskDialog(updateJob, "Updating maps complete!").ShowDialog(); 411 | 412 | BeginInvoke(new MethodInvoker(() => SetUI(true))); 413 | }); 414 | }); 415 | } 416 | 417 | private void toolStripStatusLabel2_Click(object sender, EventArgs e) 418 | { 419 | Process.Start("https://github.com/CodeStix/Beat-360fyer"); 420 | } 421 | 422 | private void buttonGeneratorSettings_Click(object sender, EventArgs e) 423 | { 424 | new FormGeneratorSettings(ref generator).ShowDialog(); 425 | var info = generator.GetInformation(); 426 | config.generatorToUse = info.Name; 427 | if (!config.generatorSettings.ContainsKey(info.Name)) 428 | config.generatorSettings.Add(info.Name, generator.Settings); 429 | else 430 | config.generatorSettings[info.Name] = generator.Settings; 431 | UpdateGeneratorSettingsButton(); 432 | } 433 | 434 | private void FormGeneratePack_FormClosing(object sender, FormClosingEventArgs e) 435 | { 436 | config.TrySave(); 437 | } 438 | 439 | private void radioButtonMusicPack_CheckedChanged(object sender, EventArgs e) 440 | { 441 | buttonGenerate.Text = "Generate Music Pack"; 442 | } 443 | 444 | private void radioButtonExport_CheckedChanged(object sender, EventArgs e) 445 | { 446 | buttonGenerate.Text = "Export to directory"; 447 | } 448 | 449 | private void radioButtonModify_CheckedChanged(object sender, EventArgs e) 450 | { 451 | buttonGenerate.Text = "Modify selected maps"; 452 | } 453 | 454 | private void UpdateGeneratorSettingsButton() 455 | { 456 | bool isDefault = BeatMapGenerator.IsDefaultSettings(generator.Settings); 457 | 458 | buttonGeneratorSettings.BackColor = isDefault ? Color.White : Color.Yellow; 459 | buttonGeneratorSettings.Text = isDefault ? "Generator settings... (default)" : "Generator settings... (modified!)"; 460 | } 461 | 462 | private void comboBoxGenerator_SelectedIndexChanged(object sender, EventArgs e) 463 | { 464 | string generatorName = (string)comboBoxGenerator.SelectedItem; 465 | generator = BeatMapGenerator.GetGeneratorWithName(generatorName); 466 | #if DEBUG 467 | Debug.Assert(generator != null); 468 | #endif 469 | if (config.generatorSettings.ContainsKey(generatorName)) 470 | generator.Settings = config.generatorSettings[generatorName]; 471 | config.generatorToUse = generatorName; 472 | 473 | var info = generator.GetInformation(); 474 | toolTipGeneratorDescription.ToolTipTitle = $"{info.Name} by {info.Author}"; 475 | toolTipGeneratorDescription.SetToolTip(comboBoxGenerator, $"{info.Description} (version {info.Version} by {info.Author})"); 476 | 477 | UpdateGeneratorSettingsButton(); 478 | } 479 | 480 | private void linkCreateGenerator_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 481 | { 482 | Process.Start("https://github.com/CodeStix/Beat-360fyer"); 483 | } 484 | } 485 | } 486 | -------------------------------------------------------------------------------- /Beat-360fyer/FormGeneratorSettings.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Stx.ThreeSixtyfyer 2 | { 3 | partial class FormGeneratorSettings 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormGeneratorSettings)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.label2 = new System.Windows.Forms.Label(); 34 | this.textBoxJson = new System.Windows.Forms.TextBox(); 35 | this.buttonSave = new System.Windows.Forms.Button(); 36 | this.buttonCancel = new System.Windows.Forms.Button(); 37 | this.textBoxError = new System.Windows.Forms.TextBox(); 38 | this.label3 = new System.Windows.Forms.Label(); 39 | this.buttonDefaults = new System.Windows.Forms.Button(); 40 | this.SuspendLayout(); 41 | // 42 | // label1 43 | // 44 | this.label1.AutoSize = true; 45 | this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 46 | this.label1.Location = new System.Drawing.Point(12, 9); 47 | this.label1.Name = "label1"; 48 | this.label1.Size = new System.Drawing.Size(154, 13); 49 | this.label1.TabIndex = 0; 50 | this.label1.Text = "Modify Generator Settings"; 51 | // 52 | // label2 53 | // 54 | this.label2.AutoSize = true; 55 | this.label2.Location = new System.Drawing.Point(12, 22); 56 | this.label2.Name = "label2"; 57 | this.label2.Size = new System.Drawing.Size(427, 26); 58 | this.label2.TabIndex = 1; 59 | this.label2.Text = "These are the generator settings in a JSON format. Only the values after the fiel" + 60 | "d \r\nnames should be edited. Please refer to the documentation on GitHub on how t" + 61 | "o edit this."; 62 | // 63 | // textBoxJson 64 | // 65 | this.textBoxJson.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 66 | this.textBoxJson.Location = new System.Drawing.Point(12, 54); 67 | this.textBoxJson.Multiline = true; 68 | this.textBoxJson.Name = "textBoxJson"; 69 | this.textBoxJson.Size = new System.Drawing.Size(465, 357); 70 | this.textBoxJson.TabIndex = 2; 71 | this.textBoxJson.TextChanged += new System.EventHandler(this.textBoxJson_TextChanged); 72 | this.textBoxJson.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBoxJson_KeyDown); 73 | // 74 | // buttonSave 75 | // 76 | this.buttonSave.Location = new System.Drawing.Point(372, 417); 77 | this.buttonSave.Name = "buttonSave"; 78 | this.buttonSave.Size = new System.Drawing.Size(105, 23); 79 | this.buttonSave.TabIndex = 3; 80 | this.buttonSave.Text = "Save && Exit"; 81 | this.buttonSave.UseVisualStyleBackColor = true; 82 | this.buttonSave.Click += new System.EventHandler(this.buttonSave_Click); 83 | // 84 | // buttonCancel 85 | // 86 | this.buttonCancel.Location = new System.Drawing.Point(12, 417); 87 | this.buttonCancel.Name = "buttonCancel"; 88 | this.buttonCancel.Size = new System.Drawing.Size(105, 23); 89 | this.buttonCancel.TabIndex = 4; 90 | this.buttonCancel.Text = "Exit"; 91 | this.buttonCancel.UseVisualStyleBackColor = true; 92 | this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); 93 | // 94 | // textBoxError 95 | // 96 | this.textBoxError.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(0))))); 97 | this.textBoxError.Location = new System.Drawing.Point(12, 466); 98 | this.textBoxError.Multiline = true; 99 | this.textBoxError.Name = "textBoxError"; 100 | this.textBoxError.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 101 | this.textBoxError.Size = new System.Drawing.Size(465, 78); 102 | this.textBoxError.TabIndex = 5; 103 | this.textBoxError.Text = "None"; 104 | // 105 | // label3 106 | // 107 | this.label3.AutoSize = true; 108 | this.label3.Location = new System.Drawing.Point(12, 450); 109 | this.label3.Name = "label3"; 110 | this.label3.Size = new System.Drawing.Size(83, 13); 111 | this.label3.TabIndex = 6; 112 | this.label3.Text = "JSON problems:"; 113 | // 114 | // buttonDefaults 115 | // 116 | this.buttonDefaults.Location = new System.Drawing.Point(235, 417); 117 | this.buttonDefaults.Name = "buttonDefaults"; 118 | this.buttonDefaults.Size = new System.Drawing.Size(131, 23); 119 | this.buttonDefaults.TabIndex = 7; 120 | this.buttonDefaults.Text = "Revert default settings"; 121 | this.buttonDefaults.UseVisualStyleBackColor = true; 122 | this.buttonDefaults.Click += new System.EventHandler(this.buttonDefaults_Click); 123 | // 124 | // FormGeneratorSettings 125 | // 126 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 127 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 128 | this.ClientSize = new System.Drawing.Size(489, 554); 129 | this.Controls.Add(this.buttonDefaults); 130 | this.Controls.Add(this.label3); 131 | this.Controls.Add(this.textBoxError); 132 | this.Controls.Add(this.buttonCancel); 133 | this.Controls.Add(this.buttonSave); 134 | this.Controls.Add(this.textBoxJson); 135 | this.Controls.Add(this.label2); 136 | this.Controls.Add(this.label1); 137 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 138 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 139 | this.MaximizeBox = false; 140 | this.Name = "FormGeneratorSettings"; 141 | this.Text = "Modify generator settings"; 142 | this.Load += new System.EventHandler(this.FormGeneratorSettings_Load); 143 | this.ResumeLayout(false); 144 | this.PerformLayout(); 145 | 146 | } 147 | 148 | #endregion 149 | 150 | private System.Windows.Forms.Label label1; 151 | private System.Windows.Forms.Label label2; 152 | private System.Windows.Forms.TextBox textBoxJson; 153 | private System.Windows.Forms.Button buttonSave; 154 | private System.Windows.Forms.Button buttonCancel; 155 | private System.Windows.Forms.TextBox textBoxError; 156 | private System.Windows.Forms.Label label3; 157 | private System.Windows.Forms.Button buttonDefaults; 158 | } 159 | } -------------------------------------------------------------------------------- /Beat-360fyer/FormGeneratorSettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace Stx.ThreeSixtyfyer 14 | { 15 | public partial class FormGeneratorSettings : Form 16 | { 17 | private IBeatMapGenerator generator; 18 | private bool saved = true; 19 | 20 | public FormGeneratorSettings(ref IBeatMapGenerator generator) 21 | { 22 | this.generator = generator; 23 | 24 | InitializeComponent(); 25 | 26 | LoadSettings(); 27 | } 28 | 29 | private void buttonSave_Click(object sender, EventArgs e) 30 | { 31 | SaveSettings(); 32 | if (saved) 33 | this.Close(); 34 | } 35 | 36 | private void LoadSettings() 37 | { 38 | textBoxJson.Text = JsonConvert.SerializeObject(this.generator.Settings, Program.JsonSettings); 39 | saved = true; 40 | } 41 | 42 | private void SaveSettings() 43 | { 44 | try 45 | { 46 | generator.Settings = JsonConvert.DeserializeObject(textBoxJson.Text, generator.Settings.GetType(), Program.JsonSettings); 47 | Message("Saved!", Color.Green); 48 | saved = true; 49 | } 50 | catch (Exception ex) 51 | { 52 | Message("Could not save: \n" + ex.Message, Color.DarkRed); 53 | } 54 | } 55 | 56 | private void Message(string message, Color color) 57 | { 58 | textBoxError.Text = $"[{DateTime.Now.ToString()}] {message}"; 59 | textBoxError.ForeColor = color; 60 | this.Height = 593; 61 | } 62 | 63 | private void FormGeneratorSettings_Load(object sender, EventArgs e) 64 | { 65 | this.Height = 488; 66 | } 67 | 68 | private void buttonCancel_Click(object sender, EventArgs e) 69 | { 70 | if (!saved && MessageBox.Show("You have unsaved changes, are you sure you want to exit?", "Not saved.", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation) != DialogResult.Yes) 71 | return; 72 | 73 | this.Close(); 74 | } 75 | 76 | private void textBoxJson_KeyDown(object sender, KeyEventArgs e) 77 | { 78 | if (e.Control && e.KeyCode == Keys.S) 79 | { 80 | SaveSettings(); 81 | } 82 | } 83 | 84 | private void buttonDefaults_Click(object sender, EventArgs e) 85 | { 86 | generator.Settings = Activator.CreateInstance(generator.Settings.GetType()); 87 | LoadSettings(); 88 | Message("Restored settings to default! (not saved yet)", Color.Green); 89 | } 90 | 91 | private void textBoxJson_TextChanged(object sender, EventArgs e) 92 | { 93 | saved = false; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Beat-360fyer/Generators/ExampleGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Stx.ThreeSixtyfyer.Generators 5 | { 6 | [BeatMapGenerator("Example 90Degree Generator", 3, "CodeStix", "This simple generator just swings to the left and to the right each x seconds.\n" + 7 | "This is to showcase how a generator is made.\n" + 8 | "Want to create your own? Check the GitHub page for instructions.")] 9 | public class ExampleGenerator : IBeatMapGenerator 10 | { 11 | public string GeneratedGameModeName => "90Degree"; 12 | public object Settings { get; set; } = new ExampleGeneratorSettings(); // Set the default settings 13 | 14 | public BeatMap FromStandard(BeatMap standard, float bpm, float timeOffset) 15 | { 16 | ExampleGeneratorSettings settings = (ExampleGeneratorSettings)Settings; 17 | BeatMap modified = new BeatMap(standard); // Copy the original map 18 | 19 | // Implement your generator's logic 20 | int direction = 0; 21 | for(int i = 0; i < modified.notes.Count; i++) 22 | { 23 | BeatMapNote currentNote = modified.notes[i]; 24 | if (i % settings.rotateEachNoteCount == 0) 25 | { 26 | if (++direction % settings.rotateCountPerDirectionSwitch < settings.rotateCountPerDirectionSwitch / 2) 27 | modified.AddGoLeftEvent(currentNote.time, 1); 28 | else 29 | modified.AddGoRightEvent(currentNote.time, 1); 30 | } 31 | } 32 | 33 | // Sort the BeatMap so that the inserted rotation events are in the right spot and not appended at the end of the events list 34 | modified.Sort(); 35 | 36 | // Return the modfied BeatMap 37 | return modified; 38 | } 39 | } 40 | 41 | // Mark Serializable 42 | [Serializable] 43 | public class ExampleGeneratorSettings 44 | { 45 | public int rotateEachNoteCount = 2; 46 | public int rotateCountPerDirectionSwitch = 4; 47 | 48 | // Override Equals() is REQUIRED to check if generator settings are equal. Update the equals condition when adding more fields. 49 | public override bool Equals(object obj) 50 | { 51 | if (obj is ExampleGeneratorSettings s) 52 | { 53 | return rotateEachNoteCount == s.rotateEachNoteCount 54 | && rotateCountPerDirectionSwitch == s.rotateCountPerDirectionSwitch; 55 | } 56 | else 57 | { 58 | return false; 59 | } 60 | } 61 | 62 | // Override GetHashCode() is recommended to check if generator settings are equal 63 | public override int GetHashCode() 64 | { 65 | int hash = 13; 66 | unchecked 67 | { 68 | hash = (hash * 7) + rotateEachNoteCount.GetHashCode(); 69 | hash = (hash * 7) + rotateCountPerDirectionSwitch.GetHashCode(); 70 | } 71 | return hash; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Beat-360fyer/GitHubBasedUpdateCheck.cs: -------------------------------------------------------------------------------- 1 | using Semver; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Stx.ThreeSixtyfyer 11 | { 12 | public class GitHubBasedUpdateCheck 13 | { 14 | //https://raw.githubusercontent.com/CodeStix/Beat-360fyer/master/Build/latestVersion.txt 15 | 16 | public string repoOwner; 17 | public string repoName; 18 | public string branch = "master"; 19 | public string versionFilePath; 20 | 21 | public string VersionFileUrl => $"https://raw.githubusercontent.com/{ repoOwner }/{ repoName }/{ branch }/{ versionFilePath }"; 22 | 23 | public GitHubBasedUpdateCheck(string repoOwner, string repoName, string versionFilePath) 24 | { 25 | this.repoOwner = repoOwner; 26 | this.repoName = repoName; 27 | this.versionFilePath = versionFilePath; 28 | } 29 | 30 | public async Task CheckForUpdate(string currentVersion) 31 | { 32 | try 33 | { 34 | using (HttpClient client = new HttpClient()) 35 | { 36 | string redVersion = await client.GetStringAsync(VersionFileUrl); 37 | Console.WriteLine("Current version: " + currentVersion); 38 | Console.WriteLine("Red version: " + redVersion); 39 | return SemVersion.Parse(redVersion) > currentVersion; 40 | } 41 | } 42 | catch 43 | { 44 | return false; 45 | } 46 | 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Beat-360fyer/HashSetExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Stx.ThreeSixtyfyer 8 | { 9 | public static class HashSetExtensions 10 | { 11 | public static void AddRange(this HashSet set, IEnumerable range) 12 | { 13 | foreach(T i in range) 14 | set.Add(i); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Beat-360fyer/IBeatMapGenerator.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Stx.ThreeSixtyfyer 3 | { 4 | public interface IBeatMapGenerator 5 | { 6 | string GeneratedGameModeName { get; } 7 | BeatMap FromStandard(BeatMap standard, float bpm, float timeOffset); 8 | object Settings { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Beat-360fyer/ICloneable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Stx.ThreeSixtyfyer 8 | { 9 | public interface ICloneable 10 | { 11 | T Clone(); 12 | } 13 | 14 | public static class IEnumerableExtensions 15 | { 16 | public static IEnumerable Clone(this IEnumerable items) where T : ICloneable 17 | { 18 | foreach (var item in items) 19 | yield return item.Clone(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Beat-360fyer/Jobs.cs: -------------------------------------------------------------------------------- 1 | using Ookii.Dialogs.Wpf; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows; 10 | 11 | namespace Stx.ThreeSixtyfyer 12 | { 13 | public static class Jobs 14 | { 15 | public static ParallelOptions MultithreadingOptions => new ParallelOptions() 16 | { 17 | MaxDegreeOfParallelism = Environment.ProcessorCount 18 | }; 19 | 20 | #region Finding songs 21 | 22 | public struct FindSongsJobResult 23 | { 24 | public List beatMaps; 25 | } 26 | 27 | public static void FindSongsUnderPath(string path, WorkerJobCompleted completed) 28 | { 29 | ProgressDialog progressDialog = new ProgressDialog(); 30 | progressDialog.ProgressBarStyle = ProgressBarStyle.MarqueeProgressBar; 31 | progressDialog.ShowCancelButton = true; 32 | progressDialog.Text = "Finding Beat Saber maps..."; 33 | progressDialog.UseCompactPathsForDescription = true; 34 | progressDialog.Description = path; 35 | progressDialog.DoWork += FindSongsUnderPath_DoWork; 36 | progressDialog.RunWorkerCompleted += (sender, e) => completed.Invoke((WorkerJob)e.Result); 37 | progressDialog.ShowDialog(null, new WorkerJob(progressDialog, path)); 38 | } 39 | 40 | private static void FindSongsUnderPath_DoWork(object sender, DoWorkEventArgs e) 41 | { 42 | WorkerJob job = (WorkerJob)e.Argument; 43 | job.result.beatMaps = new List(); 44 | e.Result = job; 45 | 46 | try 47 | { 48 | foreach (string infoFile in FileEnumerator.GetFilesRecursive(job.argument, "?nfo.dat")) 49 | { 50 | if (job.employer.CancellationPending) 51 | throw new Exception("The searching process was cancelled."); 52 | if (infoFile == null) 53 | continue; 54 | 55 | BeatMapInfo info = BeatMapInfo.FromFile(infoFile); 56 | 57 | BeatMapDifficultySet difStandardSet = info.difficultyBeatmapSets.FirstOrDefault((difs) => difs.beatmapCharacteristicName == "Standard"); 58 | if (difStandardSet == null) 59 | continue; // Cannot convert if a normal version does not exist 60 | 61 | job.result.beatMaps.Add(info); 62 | } 63 | } 64 | catch (Exception ex) 65 | { 66 | job.exceptions.Add(ex); 67 | } 68 | } 69 | 70 | #endregion // Finding songs 71 | 72 | #region Generating modes 73 | 74 | public struct GenerateMapsOptions 75 | { 76 | public HashSet difficultyLevels; 77 | public List toGenerateFor; 78 | public string destination; 79 | public bool forceGenerate; 80 | public IBeatMapGenerator generator; 81 | } 82 | 83 | public struct GeneratorMapsResult 84 | { 85 | public int mapsGenerated; 86 | public int mapsIterated; 87 | public int difficultiesGenerated; 88 | public int mapsUpToDate; 89 | public bool cancelled; 90 | } 91 | 92 | public static void GenerateMaps(GenerateMapsOptions options, WorkerJobCompleted completed) 93 | { 94 | ProgressDialog progressDialog = new ProgressDialog(); 95 | progressDialog.ShowCancelButton = true; 96 | progressDialog.WindowTitle = $"Generating modes using the {options.generator.GeneratedGameModeName}-generator..."; 97 | progressDialog.UseCompactPathsForDescription = true; 98 | progressDialog.DoWork += Generate360Maps_DoWork; 99 | progressDialog.ShowTimeRemaining = true; 100 | progressDialog.RunWorkerCompleted += (sender, e) => completed.Invoke((WorkerJob)e.Result); 101 | progressDialog.ShowDialog(null, new WorkerJob(progressDialog, options)); 102 | } 103 | 104 | private static void Generate360Maps_DoWork(object sender, DoWorkEventArgs e) 105 | { 106 | WorkerJob job = (WorkerJob)e.Argument; 107 | e.Result = job; 108 | 109 | Parallel.For(0, job.argument.toGenerateFor.Count, MultithreadingOptions, (i) => { 110 | 111 | if (job.employer.CancellationPending && !job.result.cancelled) 112 | job.result.cancelled = true; 113 | if (job.result.cancelled) 114 | return; 115 | 116 | BeatMapInfo info; 117 | lock (job.argument.toGenerateFor) 118 | info = job.argument.toGenerateFor[i]; 119 | 120 | BeatMapGenerator.Result r; 121 | if (string.IsNullOrEmpty(job.argument.destination)) 122 | r = BeatMapGenerator.UseGeneratorAndOverwrite(job.argument.generator, info, job.argument.difficultyLevels, job.argument.forceGenerate); 123 | else 124 | r = BeatMapGenerator.UseGeneratorAndCopy(job.argument.generator, info, job.argument.difficultyLevels, job.argument.destination, job.argument.forceGenerate); 125 | 126 | job.result.difficultiesGenerated += r.generatedCount; 127 | if (r.generatedCount != 0) 128 | job.result.mapsGenerated++; 129 | if (r.alreadyUpToDate) 130 | job.result.mapsUpToDate++; 131 | job.result.mapsIterated++; 132 | job.Report((int)((float)job.result.mapsIterated / job.argument.toGenerateFor.Count * 100f), info.ToString(), info.mapDirectoryPath); 133 | }); 134 | 135 | if (job.result.cancelled) 136 | job.exceptions.Add(new Exception("The generation process was cancelled.")); 137 | } 138 | 139 | #endregion 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Beat-360fyer/Program.cs: -------------------------------------------------------------------------------- 1 | using Ookii.Dialogs.Wpf; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | using Newtonsoft.Json; 10 | 11 | namespace Stx.ThreeSixtyfyer 12 | { 13 | static class Program 14 | { 15 | public static JsonSerializerSettings JsonSettings => new JsonSerializerSettings() 16 | { 17 | TypeNameHandling = TypeNameHandling.Auto, 18 | Formatting = Formatting.Indented 19 | }; 20 | 21 | 22 | /// 23 | /// The main entry point for the application. 24 | /// 25 | [STAThread] 26 | static void Main() 27 | { 28 | Application.EnableVisualStyles(); 29 | Application.SetCompatibleTextRenderingDefault(false); 30 | Application.Run(new FormGeneratePack()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Beat-360fyer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Beat-360fyer")] 9 | [assembly: AssemblyDescription("Tool to convert a normal Beat Saber level into a 360 one!")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Stijn Rogiest")] 12 | [assembly: AssemblyProduct("Beat-360fyer")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5177250d-f5bb-4f36-a68d-f4f0281993a6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2.1.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Beat-360fyer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Stx.ThreeSixtyfyer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stx.ThreeSixtyfyer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap PackThumbnail { 67 | get { 68 | object obj = ResourceManager.GetObject("PackThumbnail", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Beat-360fyer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\360.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /Beat-360fyer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Stx.ThreeSixtyfyer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Beat-360fyer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Beat-360fyer/ThreeSixtyfyerConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Stx.ThreeSixtyfyer 4 | { 5 | public class ThreeSixtyfyerConfig : Config 6 | { 7 | public override int Version => 1; 8 | 9 | public string packPath; 10 | public string bulkPath; 11 | public string exportPath; 12 | public string lastGeneratedMusicPackSourcePath; 13 | public string lastGeneratedMusicPackPath; 14 | 15 | public string generatorToUse = BeatMapGenerator.DefaultGenerator.GetInformation().Name; 16 | public Dictionary generatorSettings = new Dictionary(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Beat-360fyer/WorkerJob.cs: -------------------------------------------------------------------------------- 1 | using Ookii.Dialogs.Wpf; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Stx.ThreeSixtyfyer 9 | { 10 | public delegate void WorkerJobCompleted(WorkerJob job); 11 | 12 | public class WorkerJob 13 | { 14 | public WorkerJob(ProgressDialog employer, T argument = default) 15 | { 16 | this.employer = employer; 17 | this.argument = argument; 18 | } 19 | 20 | public ProgressDialog employer; 21 | public T argument; 22 | public List exceptions = new List(); 23 | public U result; 24 | 25 | public void Report(int percentage) 26 | => employer?.ReportProgress(percentage); 27 | public void Report(int percentage, string text, string description) 28 | => employer?.ReportProgress(percentage, text, description); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Beat-360fyer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Build/360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/360.png -------------------------------------------------------------------------------- /Build/Beat-360fyer v1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Beat-360fyer v1.0.zip -------------------------------------------------------------------------------- /Build/Beat-360fyer v2.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Beat-360fyer v2.0.zip -------------------------------------------------------------------------------- /Build/Demos/Beat It.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Beat It.zip -------------------------------------------------------------------------------- /Build/Demos/Beat it (old version).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Beat it (old version).zip -------------------------------------------------------------------------------- /Build/Demos/Boulevard of Broken Dreams.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Boulevard of Broken Dreams.zip -------------------------------------------------------------------------------- /Build/Demos/Jaroslav Beck - Beat Saber (old version).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Jaroslav Beck - Beat Saber (old version).zip -------------------------------------------------------------------------------- /Build/Demos/Pokemon Theme Song.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Pokemon Theme Song.zip -------------------------------------------------------------------------------- /Build/Demos/Riot - Overkill.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/Riot - Overkill.zip -------------------------------------------------------------------------------- /Build/Demos/beatsaber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/Demos/beatsaber.gif -------------------------------------------------------------------------------- /Build/latestVersion.txt: -------------------------------------------------------------------------------- 1 | 2.0.0 -------------------------------------------------------------------------------- /Build/sabers.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Build/sabers.ico -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stijn Rogiest 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Beat-360fyer 2 | 3 | **⚠️ There is now a Beat Saber plugin that makes this much easier. You can find it [here](https://github.com/CodeStix/Beat-360fyer-Plugin).** 4 | 5 | This desktop application is used to generate 360 levels from standard Beat Saber levels. 6 | 7 | ![Jaroslav Beck - Beat Saber, converted on the right, standard on the left](https://github.com/CodeStix/Beat-360fyer/raw/master/Build/Demos/beatsaber.gif) 8 | 9 | *(Jaroslav Beck - Beat Saber) Left: Standard; Right: Generated 360 mode* 10 | 11 | ## :computer: How to use it? 12 | ### Generate a Music Pack (recommended) (requires *SongCore*) 13 | 1. Make sure you have the [SongCore (by Kylemc1413)](https://github.com/Kylemc1413/SongCore) mod installed, this is required to create custom music packs. 14 | 2. Download the tool from the [releases page](https://github.com/CodeStix/Beat-360fyer/releases) & unzip. 15 | 3. Execute `Beat-360fyer.exe`. 16 | 4. Select `Generate Music Pack`. 17 | 5. Select your Beat Saber directory. 18 | 6. Choose the levels which you want a 360 mode for. 19 | 7. Press the generate button, it will copy all the chosen songs and then generates new gamemodes. 20 | 8. Wait for the process to finish. 21 | 9. Start up Beat Saber, a music pack should appear named 'Generated 360 levels'. 22 | ### Generate and modify (for map makers) 23 | > :warning: **Not recommended for normal use, will break ScoreSaber on standard levels!** 24 | 1. Download the tool from the [releases page](https://github.com/CodeStix/Beat-360fyer/releases) & unzip. 25 | 2. Execute `Beat-360fyer.exe`. 26 | 3. Select `Generate And Overwrite`. 27 | 4. Select your Beat Saber directory. 28 | 5. Choose the levels which you want a 360 mode for. 29 | 6. Press the generate button, it will modify the `Info.dat` of the chosen levels, and then generate new gamemodes. 30 | 7. Wait for the process to finish. 31 | 8. The selected maps now have a 360 mode. 32 | 33 | ## :mag: Demos 34 | Here are some demo levels, generated with this tool: (created with this tool at version 2.0.0) 35 | - [Boulevard of Broken Dreams](https://github.com/CodeStix/Beat-360fyer/raw/master/Build/Demos/Boulevard%20of%20Broken%20Dreams.zip) 36 | - [Pokemon Theme Song](https://github.com/CodeStix/Beat-360fyer/raw/master/Build/Demos/Pokemon%20Theme%20Song.zip) 37 | - [Riot - Overkill](https://github.com/CodeStix/Beat-360fyer/raw/master/Build/Demos/Riot%20-%20Overkill.zip) 38 | - [Beat It](https://github.com/CodeStix/Beat-360fyer/raw/master/Build/Demos/Beat%20it.zip) 39 | -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/Easy.dat: -------------------------------------------------------------------------------- 1 | {"_version":"2.0.0","_events":[{"_time":0.0,"_type":4,"_value":5},{"_time":8.0,"_type":0,"_value":2},{"_time":8.0,"_type":4,"_value":2},{"_time":16.0,"_type":0,"_value":0},{"_time":16.0,"_type":4,"_value":5},{"_time":24.0,"_type":1,"_value":2},{"_time":24.0,"_type":4,"_value":1},{"_time":32.0,"_type":1,"_value":0},{"_time":32.0,"_type":4,"_value":5},{"_time":40.0,"_type":0,"_value":2},{"_time":40.0,"_type":1,"_value":2},{"_time":40.0,"_type":4,"_value":1},{"_time":40.0,"_type":8,"_value":0},{"_time":48.0,"_type":0,"_value":0},{"_time":48.0,"_type":1,"_value":0},{"_time":48.0,"_type":2,"_value":2},{"_time":48.0,"_type":8,"_value":0},{"_time":52.0,"_type":2,"_value":0},{"_time":52.0,"_type":3,"_value":2},{"_time":52.0,"_type":8,"_value":0},{"_time":56.0,"_type":2,"_value":2},{"_time":56.0,"_type":3,"_value":2},{"_time":56.0,"_type":4,"_value":2},{"_time":56.0,"_type":8,"_value":0},{"_time":56.0,"_type":9,"_value":1},{"_time":64.0,"_type":1,"_value":2},{"_time":64.0,"_type":2,"_value":2},{"_time":64.0,"_type":3,"_value":2},{"_time":64.0,"_type":4,"_value":2},{"_time":64.0,"_type":8,"_value":0},{"_time":64.0,"_type":9,"_value":0},{"_time":68.0,"_type":0,"_value":3},{"_time":68.0,"_type":1,"_value":3},{"_time":68.0,"_type":2,"_value":3},{"_time":68.0,"_type":3,"_value":3},{"_time":68.0,"_type":4,"_value":5},{"_time":72.0,"_type":0,"_value":3},{"_time":72.0,"_type":1,"_value":3},{"_time":72.0,"_type":2,"_value":2},{"_time":72.0,"_type":3,"_value":2},{"_time":72.0,"_type":4,"_value":2},{"_time":72.0,"_type":8,"_value":0},{"_time":72.0,"_type":9,"_value":1},{"_time":72.0,"_type":12,"_value":5},{"_time":72.0,"_type":13,"_value":5},{"_time":75.0,"_type":3,"_value":2},{"_time":76.0,"_type":2,"_value":6},{"_time":76.0,"_type":3,"_value":6},{"_time":76.0,"_type":4,"_value":6},{"_time":76.0,"_type":8,"_value":0},{"_time":79.0,"_type":3,"_value":6},{"_time":80.0,"_type":0,"_value":3},{"_time":80.0,"_type":1,"_value":3},{"_time":80.0,"_type":2,"_value":2},{"_time":80.0,"_type":3,"_value":0},{"_time":80.0,"_type":4,"_value":1},{"_time":80.0,"_type":12,"_value":5},{"_time":80.0,"_type":13,"_value":5},{"_time":83.0,"_type":3,"_value":2},{"_time":84.0,"_type":2,"_value":2},{"_time":84.0,"_type":8,"_value":0},{"_time":86.0,"_type":3,"_value":1},{"_time":88.0,"_type":0,"_value":3},{"_time":88.0,"_type":1,"_value":3},{"_time":88.0,"_type":2,"_value":1},{"_time":88.0,"_type":12,"_value":5},{"_time":88.0,"_type":13,"_value":5},{"_time":91.0,"_type":3,"_value":2},{"_time":92.0,"_type":2,"_value":6},{"_time":92.0,"_type":3,"_value":6},{"_time":92.0,"_type":4,"_value":6},{"_time":92.0,"_type":8,"_value":0},{"_time":96.0,"_type":0,"_value":3},{"_time":96.0,"_type":1,"_value":3},{"_time":96.0,"_type":2,"_value":1},{"_time":96.0,"_type":3,"_value":0},{"_time":96.0,"_type":4,"_value":1},{"_time":96.0,"_type":12,"_value":5},{"_time":96.0,"_type":13,"_value":5},{"_time":99.0,"_type":2,"_value":0},{"_time":99.0,"_type":4,"_value":6},{"_time":100.0,"_type":0,"_value":0},{"_time":100.0,"_type":1,"_value":0},{"_time":100.0,"_type":2,"_value":1},{"_time":100.0,"_type":4,"_value":1},{"_time":100.0,"_type":8,"_value":0},{"_time":100.0,"_type":12,"_value":0},{"_time":102.0,"_type":3,"_value":1},{"_time":102.0,"_type":13,"_value":0},{"_time":103.0,"_type":8,"_value":0},{"_time":104.0,"_type":0,"_value":2},{"_time":104.0,"_type":1,"_value":3},{"_time":104.0,"_type":2,"_value":2},{"_time":104.0,"_type":3,"_value":2},{"_time":104.0,"_type":4,"_value":2},{"_time":104.0,"_type":8,"_value":0},{"_time":104.0,"_type":9,"_value":1},{"_time":104.0,"_type":12,"_value":5},{"_time":104.0,"_type":13,"_value":5},{"_time":108.0,"_type":0,"_value":6},{"_time":108.0,"_type":1,"_value":7},{"_time":108.0,"_type":2,"_value":6},{"_time":108.0,"_type":3,"_value":6},{"_time":108.0,"_type":4,"_value":5},{"_time":112.0,"_type":0,"_value":2},{"_time":112.0,"_type":1,"_value":3},{"_time":112.0,"_type":2,"_value":2},{"_time":112.0,"_type":3,"_value":2},{"_time":112.0,"_type":4,"_value":1},{"_time":112.0,"_type":8,"_value":0},{"_time":112.0,"_type":12,"_value":5},{"_time":112.0,"_type":13,"_value":5},{"_time":116.0,"_type":0,"_value":6},{"_time":116.0,"_type":1,"_value":7},{"_time":116.0,"_type":2,"_value":6},{"_time":116.0,"_type":3,"_value":6},{"_time":116.0,"_type":4,"_value":5},{"_time":118.0,"_type":2,"_value":7},{"_time":118.0,"_type":3,"_value":7},{"_time":120.0,"_type":0,"_value":2},{"_time":120.0,"_type":1,"_value":0},{"_time":120.0,"_type":3,"_value":2},{"_time":120.0,"_type":4,"_value":1},{"_time":120.0,"_type":8,"_value":0},{"_time":120.0,"_type":12,"_value":5},{"_time":120.0,"_type":13,"_value":5},{"_time":121.0,"_type":2,"_value":2},{"_time":123.0,"_type":2,"_value":3},{"_time":123.0,"_type":3,"_value":3},{"_time":124.0,"_type":0,"_value":0},{"_time":124.0,"_type":1,"_value":6},{"_time":124.0,"_type":3,"_value":6},{"_time":124.0,"_type":4,"_value":5},{"_time":124.0,"_type":8,"_value":0},{"_time":125.0,"_type":2,"_value":6},{"_time":127.0,"_type":1,"_value":0},{"_time":128.0,"_type":2,"_value":0},{"_time":128.0,"_type":3,"_value":0},{"_time":128.0,"_type":4,"_value":1},{"_time":128.0,"_type":8,"_value":0},{"_time":128.0,"_type":9,"_value":0},{"_time":130.0,"_type":0,"_value":1},{"_time":132.0,"_type":0,"_value":0},{"_time":132.0,"_type":1,"_value":3},{"_time":132.0,"_type":8,"_value":0},{"_time":132.0,"_type":9,"_value":1},{"_time":133.0,"_type":0,"_value":3},{"_time":133.0,"_type":1,"_value":0},{"_time":134.0,"_type":2,"_value":0},{"_time":134.0,"_type":3,"_value":3},{"_time":134.0,"_type":13,"_value":0},{"_time":135.0,"_type":2,"_value":3},{"_time":135.0,"_type":3,"_value":0},{"_time":135.0,"_type":12,"_value":0},{"_time":136.0,"_type":0,"_value":7},{"_time":136.0,"_type":2,"_value":7},{"_time":136.0,"_type":3,"_value":7},{"_time":136.0,"_type":4,"_value":6},{"_time":136.0,"_type":8,"_value":0},{"_time":136.0,"_type":9,"_value":0},{"_time":144.0,"_type":1,"_value":3},{"_time":144.0,"_type":4,"_value":2},{"_time":144.0,"_type":8,"_value":0},{"_time":144.0,"_type":9,"_value":1},{"_time":152.0,"_type":0,"_value":7},{"_time":152.0,"_type":4,"_value":6},{"_time":152.0,"_type":8,"_value":0},{"_time":152.0,"_type":9,"_value":0},{"_time":160.0,"_type":1,"_value":3},{"_time":160.0,"_type":4,"_value":2},{"_time":160.0,"_type":8,"_value":0},{"_time":160.0,"_type":9,"_value":1},{"_time":168.0,"_type":0,"_value":7},{"_time":168.0,"_type":4,"_value":6},{"_time":168.0,"_type":8,"_value":0},{"_time":168.0,"_type":9,"_value":0},{"_time":176.0,"_type":1,"_value":3},{"_time":176.0,"_type":4,"_value":2},{"_time":176.0,"_type":8,"_value":0},{"_time":176.0,"_type":9,"_value":1},{"_time":184.0,"_type":0,"_value":2},{"_time":184.0,"_type":2,"_value":3},{"_time":184.0,"_type":3,"_value":3},{"_time":184.0,"_type":8,"_value":0},{"_time":184.0,"_type":9,"_value":0},{"_time":192.0,"_type":0,"_value":3},{"_time":192.0,"_type":2,"_value":3},{"_time":192.0,"_type":3,"_value":3},{"_time":192.0,"_type":4,"_value":2},{"_time":192.0,"_type":8,"_value":0},{"_time":192.0,"_type":9,"_value":1},{"_time":198.0,"_type":0,"_value":3},{"_time":198.0,"_type":1,"_value":0},{"_time":198.0,"_type":2,"_value":0},{"_time":198.0,"_type":3,"_value":0},{"_time":198.0,"_type":4,"_value":0},{"_time":198.5,"_type":1,"_value":3},{"_time":199.0,"_type":4,"_value":3},{"_time":200.0,"_type":0,"_value":3},{"_time":200.0,"_type":1,"_value":3},{"_time":200.0,"_type":2,"_value":2},{"_time":200.0,"_type":3,"_value":2},{"_time":200.0,"_type":4,"_value":3},{"_time":200.0,"_type":8,"_value":0},{"_time":200.0,"_type":9,"_value":1},{"_time":200.0,"_type":12,"_value":5},{"_time":200.0,"_type":13,"_value":5},{"_time":202.0,"_type":0,"_value":3},{"_time":202.0,"_type":1,"_value":3},{"_time":202.0,"_type":4,"_value":3},{"_time":204.0,"_type":2,"_value":2},{"_time":204.0,"_type":3,"_value":2},{"_time":204.0,"_type":8,"_value":0},{"_time":206.0,"_type":0,"_value":3},{"_time":206.0,"_type":4,"_value":3},{"_time":207.0,"_type":1,"_value":3},{"_time":208.0,"_type":0,"_value":3},{"_time":208.0,"_type":1,"_value":3},{"_time":208.0,"_type":4,"_value":3},{"_time":208.0,"_type":8,"_value":0},{"_time":208.0,"_type":12,"_value":5},{"_time":208.0,"_type":13,"_value":5},{"_time":210.0,"_type":0,"_value":3},{"_time":210.0,"_type":1,"_value":3},{"_time":210.0,"_type":4,"_value":3},{"_time":212.0,"_type":2,"_value":2},{"_time":212.0,"_type":3,"_value":2},{"_time":212.0,"_type":8,"_value":0},{"_time":214.0,"_type":1,"_value":3},{"_time":215.0,"_type":0,"_value":3},{"_time":215.0,"_type":4,"_value":3},{"_time":216.0,"_type":0,"_value":3},{"_time":216.0,"_type":1,"_value":3},{"_time":216.0,"_type":4,"_value":3},{"_time":216.0,"_type":8,"_value":0},{"_time":216.0,"_type":12,"_value":5},{"_time":216.0,"_type":13,"_value":5},{"_time":218.0,"_type":0,"_value":3},{"_time":218.0,"_type":1,"_value":3},{"_time":218.0,"_type":4,"_value":3},{"_time":220.0,"_type":2,"_value":2},{"_time":220.0,"_type":3,"_value":2},{"_time":220.0,"_type":8,"_value":0},{"_time":222.0,"_type":0,"_value":3},{"_time":223.0,"_type":1,"_value":3},{"_time":223.0,"_type":4,"_value":3},{"_time":224.0,"_type":0,"_value":3},{"_time":224.0,"_type":1,"_value":3},{"_time":224.0,"_type":4,"_value":3},{"_time":224.0,"_type":8,"_value":0},{"_time":224.0,"_type":12,"_value":5},{"_time":224.0,"_type":13,"_value":5},{"_time":226.0,"_type":0,"_value":3},{"_time":226.0,"_type":1,"_value":3},{"_time":226.0,"_type":4,"_value":3},{"_time":228.0,"_type":2,"_value":2},{"_time":228.0,"_type":3,"_value":2},{"_time":228.0,"_type":8,"_value":0},{"_time":230.0,"_type":1,"_value":3},{"_time":231.0,"_type":1,"_value":3},{"_time":232.0,"_type":0,"_value":3},{"_time":232.0,"_type":1,"_value":3},{"_time":232.0,"_type":4,"_value":2},{"_time":232.0,"_type":8,"_value":0},{"_time":232.0,"_type":12,"_value":5},{"_time":232.0,"_type":13,"_value":5},{"_time":234.0,"_type":1,"_value":3},{"_time":236.0,"_type":0,"_value":3},{"_time":236.0,"_type":8,"_value":0},{"_time":237.0,"_type":1,"_value":3},{"_time":238.0,"_type":1,"_value":3},{"_time":240.0,"_type":1,"_value":3},{"_time":240.0,"_type":4,"_value":2},{"_time":240.0,"_type":8,"_value":0},{"_time":240.0,"_type":12,"_value":6},{"_time":240.0,"_type":13,"_value":6},{"_time":242.0,"_type":0,"_value":3},{"_time":244.0,"_type":1,"_value":3},{"_time":244.0,"_type":8,"_value":0},{"_time":245.0,"_type":0,"_value":3},{"_time":246.0,"_type":1,"_value":3},{"_time":247.0,"_type":1,"_value":3},{"_time":249.0,"_type":0,"_value":3},{"_time":249.0,"_type":1,"_value":3},{"_time":249.0,"_type":2,"_value":2},{"_time":249.0,"_type":3,"_value":2},{"_time":249.0,"_type":4,"_value":2},{"_time":249.0,"_type":12,"_value":7},{"_time":249.0,"_type":13,"_value":7},{"_time":252.0,"_type":0,"_value":3},{"_time":252.0,"_type":8,"_value":0},{"_time":254.0,"_type":1,"_value":3},{"_time":256.0,"_type":0,"_value":3},{"_time":256.0,"_type":4,"_value":2},{"_time":256.0,"_type":8,"_value":0},{"_time":257.0,"_type":1,"_value":3},{"_time":258.0,"_type":0,"_value":3},{"_time":259.0,"_type":1,"_value":3},{"_time":260.0,"_type":0,"_value":3},{"_time":260.0,"_type":1,"_value":0},{"_time":260.0,"_type":2,"_value":0},{"_time":260.0,"_type":3,"_value":0},{"_time":260.0,"_type":4,"_value":3},{"_time":260.0,"_type":8,"_value":0},{"_time":260.0,"_type":12,"_value":0},{"_time":260.0,"_type":13,"_value":0},{"_time":261.0,"_type":2,"_value":3},{"_time":261.0,"_type":3,"_value":3},{"_time":262.0,"_type":0,"_value":7},{"_time":262.0,"_type":4,"_value":7},{"_time":263.0,"_type":1,"_value":7},{"_time":264.0,"_type":0,"_value":2},{"_time":264.0,"_type":1,"_value":3},{"_time":264.0,"_type":2,"_value":2},{"_time":264.0,"_type":3,"_value":2},{"_time":264.0,"_type":4,"_value":3},{"_time":264.0,"_type":8,"_value":0},{"_time":264.0,"_type":9,"_value":0},{"_time":272.0,"_type":0,"_value":7},{"_time":272.0,"_type":1,"_value":6},{"_time":272.0,"_type":2,"_value":0},{"_time":272.0,"_type":3,"_value":0},{"_time":272.0,"_type":4,"_value":6},{"_time":272.0,"_type":8,"_value":0},{"_time":272.0,"_type":9,"_value":1},{"_time":280.0,"_type":0,"_value":2},{"_time":280.0,"_type":1,"_value":3},{"_time":280.0,"_type":2,"_value":2},{"_time":280.0,"_type":3,"_value":2},{"_time":280.0,"_type":4,"_value":3},{"_time":280.0,"_type":8,"_value":0},{"_time":280.0,"_type":9,"_value":0},{"_time":288.0,"_type":0,"_value":6},{"_time":288.0,"_type":1,"_value":6},{"_time":288.0,"_type":2,"_value":0},{"_time":288.0,"_type":3,"_value":0},{"_time":288.0,"_type":4,"_value":0},{"_time":288.0,"_type":8,"_value":0},{"_time":288.0,"_type":9,"_value":1},{"_time":296.0,"_type":0,"_value":7},{"_time":296.0,"_type":1,"_value":7},{"_time":296.0,"_type":2,"_value":7},{"_time":296.0,"_type":3,"_value":7},{"_time":296.0,"_type":4,"_value":6},{"_time":296.0,"_type":8,"_value":0},{"_time":296.0,"_type":9,"_value":0}],"_notes":[{"_time":8.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":14.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":16.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":24.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":30.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":32.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":36.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":40.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":48.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":52.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":56.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":62.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":64.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":68.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":72.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":75.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":76.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":79.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":80.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":83.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":84.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":88.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":91.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":92.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":95.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":96.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":99.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":100.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":104.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":107.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":108.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":111.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":112.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":115.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":116.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":120.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":123.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":124.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":127.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":128.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":132.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":134.0,"_lineIndex":0,"_lineLayer":1,"_type":0,"_cutDirection":2},{"_time":136.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":136.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":144.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":144.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":152.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":152.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":160.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":160.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":168.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":3},{"_time":168.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":176.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":2},{"_time":176.0,"_lineIndex":0,"_lineLayer":1,"_type":0,"_cutDirection":2},{"_time":184.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":184.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":192.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":192.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":200.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":202.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":206.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":208.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":210.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":214.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":216.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":218.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":222.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":224.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":226.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":230.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":232.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":234.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":236.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":238.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":240.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":242.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":244.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":248.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":250.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":252.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":254.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":256.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":260.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":262.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":264.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":264.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":272.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":272.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":280.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":280.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":288.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":288.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":296.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":296.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1}],"_obstacles":[{"_time":72.0,"_lineIndex":3,"_type":0,"_duration":8.0,"_width":1},{"_time":88.0,"_lineIndex":0,"_type":0,"_duration":8.0,"_width":1},{"_time":168.0,"_lineIndex":0,"_type":0,"_duration":2.0,"_width":1},{"_time":170.0,"_lineIndex":1,"_type":0,"_duration":2.0,"_width":1},{"_time":176.0,"_lineIndex":3,"_type":0,"_duration":2.0,"_width":1},{"_time":178.0,"_lineIndex":2,"_type":0,"_duration":2.0,"_width":1},{"_time":186.0,"_lineIndex":0,"_type":1,"_duration":2.0,"_width":4}]} -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/Info.dat: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "2.0.0", 3 | "_songName": "Beat Saber", 4 | "_songSubName": "", 5 | "_songAuthorName": "Jaroslav Beck", 6 | "_levelAuthorName": "", 7 | "_beatsPerMinute": 166.0, 8 | "_songTimeOffset": 0.0, 9 | "_shuffle": 0.0, 10 | "_shufflePeriod": 1.0, 11 | "_previewStartTime": 26.0, 12 | "_previewDuration": 12.0, 13 | "_songFilename": "song.ogg", 14 | "_coverImageFilename": "cover.png", 15 | "_environmentName": "DefaultEnvironment", 16 | "_allDirectionsEnvironmentName": "GlassDesertEnvironment", 17 | "_difficultyBeatmapSets": [ 18 | { 19 | "_beatmapCharacteristicName": "Standard", 20 | "_difficultyBeatmaps": [ 21 | { 22 | "_difficulty": "Easy", 23 | "_difficultyRank": 1, 24 | "_beatmapFilename": "Easy.dat", 25 | "_noteJumpMovementSpeed": 0.0, 26 | "_noteJumpStartBeatOffset": 0.0 27 | }, 28 | { 29 | "_difficulty": "Normal", 30 | "_difficultyRank": 3, 31 | "_beatmapFilename": "Normal.dat", 32 | "_noteJumpMovementSpeed": 0.0, 33 | "_noteJumpStartBeatOffset": 0.0 34 | }, 35 | { 36 | "_difficulty": "Hard", 37 | "_difficultyRank": 5, 38 | "_beatmapFilename": "Hard.dat", 39 | "_noteJumpMovementSpeed": 0.0, 40 | "_noteJumpStartBeatOffset": 0.0 41 | }, 42 | { 43 | "_difficulty": "Expert", 44 | "_difficultyRank": 7, 45 | "_beatmapFilename": "Expert.dat", 46 | "_noteJumpMovementSpeed": 0.0, 47 | "_noteJumpStartBeatOffset": 0.0 48 | }, 49 | { 50 | "_difficulty": "ExpertPlus", 51 | "_difficultyRank": 9, 52 | "_beatmapFilename": "ExpertPlus.dat", 53 | "_noteJumpMovementSpeed": 0.0, 54 | "_noteJumpStartBeatOffset": 1.0 55 | } 56 | ] 57 | }, 58 | { 59 | "_beatmapCharacteristicName": "OneSaber", 60 | "_difficultyBeatmaps": [ 61 | { 62 | "_difficulty": "Expert", 63 | "_difficultyRank": 7, 64 | "_beatmapFilename": "OneSaberExpert.dat", 65 | "_noteJumpMovementSpeed": 0.0, 66 | "_noteJumpStartBeatOffset": 0.0 67 | } 68 | ] 69 | }, 70 | { 71 | "_beatmapCharacteristicName": "NoArrows", 72 | "_difficultyBeatmaps": [ 73 | { 74 | "_difficulty": "Easy", 75 | "_difficultyRank": 1, 76 | "_beatmapFilename": "NoArrowsEasy.dat", 77 | "_noteJumpMovementSpeed": 0.0, 78 | "_noteJumpStartBeatOffset": 0.0 79 | }, 80 | { 81 | "_difficulty": "Normal", 82 | "_difficultyRank": 3, 83 | "_beatmapFilename": "NoArrowsNormal.dat", 84 | "_noteJumpMovementSpeed": 0.0, 85 | "_noteJumpStartBeatOffset": 0.0 86 | }, 87 | { 88 | "_difficulty": "Hard", 89 | "_difficultyRank": 5, 90 | "_beatmapFilename": "NoArrowsHard.dat", 91 | "_noteJumpMovementSpeed": 0.0, 92 | "_noteJumpStartBeatOffset": 0.0 93 | }, 94 | { 95 | "_difficulty": "Expert", 96 | "_difficultyRank": 7, 97 | "_beatmapFilename": "NoArrowsExpert.dat", 98 | "_noteJumpMovementSpeed": 0.0, 99 | "_noteJumpStartBeatOffset": 0.0 100 | } 101 | ] 102 | }, 103 | { 104 | "_beatmapCharacteristicName": "360Degree", 105 | "_difficultyBeatmaps": [ 106 | { 107 | "_difficulty": "Easy", 108 | "_difficultyRank": 1, 109 | "_beatmapFilename": "360DegreeEasy.dat", 110 | "_noteJumpMovementSpeed": 0.0, 111 | "_noteJumpStartBeatOffset": 0.0 112 | }, 113 | { 114 | "_difficulty": "Hard", 115 | "_difficultyRank": 5, 116 | "_beatmapFilename": "360DegreeHard.dat", 117 | "_noteJumpMovementSpeed": 0.0, 118 | "_noteJumpStartBeatOffset": 0.0 119 | }, 120 | { 121 | "_difficulty": "Expert", 122 | "_difficultyRank": 7, 123 | "_beatmapFilename": "360DegreeExpert.dat", 124 | "_noteJumpMovementSpeed": 0.0, 125 | "_noteJumpStartBeatOffset": 0.0 126 | }, 127 | { 128 | "_difficulty": "ExpertPlus", 129 | "_difficultyRank": 9, 130 | "_beatmapFilename": "360DegreeExpertPlus.dat", 131 | "_noteJumpMovementSpeed": 0.0, 132 | "_noteJumpStartBeatOffset": 0.0 133 | } 134 | ] 135 | }, 136 | { 137 | "_beatmapCharacteristicName": "90Degree", 138 | "_difficultyBeatmaps": [ 139 | { 140 | "_difficulty": "Easy", 141 | "_difficultyRank": 1, 142 | "_beatmapFilename": "90DegreeEasy.dat", 143 | "_noteJumpMovementSpeed": 0.0, 144 | "_noteJumpStartBeatOffset": 0.0 145 | } 146 | ] 147 | } 148 | ] 149 | } 150 | -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/NoArrowsEasy.dat: -------------------------------------------------------------------------------- 1 | {"_version":"2.0.0","_events":[{"_time":0.0,"_type":4,"_value":5},{"_time":8.0,"_type":0,"_value":2},{"_time":8.0,"_type":4,"_value":2},{"_time":16.0,"_type":0,"_value":0},{"_time":16.0,"_type":4,"_value":5},{"_time":24.0,"_type":1,"_value":2},{"_time":24.0,"_type":4,"_value":1},{"_time":32.0,"_type":1,"_value":0},{"_time":32.0,"_type":4,"_value":5},{"_time":40.0,"_type":0,"_value":2},{"_time":40.0,"_type":1,"_value":2},{"_time":40.0,"_type":4,"_value":1},{"_time":40.0,"_type":8,"_value":0},{"_time":48.0,"_type":0,"_value":0},{"_time":48.0,"_type":1,"_value":0},{"_time":48.0,"_type":2,"_value":2},{"_time":48.0,"_type":8,"_value":0},{"_time":52.0,"_type":2,"_value":0},{"_time":52.0,"_type":3,"_value":2},{"_time":52.0,"_type":8,"_value":0},{"_time":56.0,"_type":2,"_value":2},{"_time":56.0,"_type":3,"_value":2},{"_time":56.0,"_type":4,"_value":2},{"_time":56.0,"_type":8,"_value":0},{"_time":56.0,"_type":9,"_value":1},{"_time":64.0,"_type":1,"_value":2},{"_time":64.0,"_type":2,"_value":2},{"_time":64.0,"_type":3,"_value":2},{"_time":64.0,"_type":4,"_value":2},{"_time":64.0,"_type":8,"_value":0},{"_time":64.0,"_type":9,"_value":0},{"_time":68.0,"_type":0,"_value":3},{"_time":68.0,"_type":1,"_value":3},{"_time":68.0,"_type":2,"_value":3},{"_time":68.0,"_type":3,"_value":3},{"_time":68.0,"_type":4,"_value":5},{"_time":72.0,"_type":0,"_value":3},{"_time":72.0,"_type":1,"_value":3},{"_time":72.0,"_type":2,"_value":2},{"_time":72.0,"_type":3,"_value":2},{"_time":72.0,"_type":4,"_value":2},{"_time":72.0,"_type":8,"_value":0},{"_time":72.0,"_type":9,"_value":1},{"_time":72.0,"_type":12,"_value":5},{"_time":72.0,"_type":13,"_value":5},{"_time":75.0,"_type":3,"_value":2},{"_time":76.0,"_type":2,"_value":6},{"_time":76.0,"_type":3,"_value":6},{"_time":76.0,"_type":4,"_value":6},{"_time":76.0,"_type":8,"_value":0},{"_time":79.0,"_type":3,"_value":6},{"_time":80.0,"_type":0,"_value":3},{"_time":80.0,"_type":1,"_value":3},{"_time":80.0,"_type":2,"_value":2},{"_time":80.0,"_type":3,"_value":0},{"_time":80.0,"_type":4,"_value":1},{"_time":80.0,"_type":12,"_value":5},{"_time":80.0,"_type":13,"_value":5},{"_time":83.0,"_type":3,"_value":2},{"_time":84.0,"_type":2,"_value":2},{"_time":84.0,"_type":8,"_value":0},{"_time":86.0,"_type":3,"_value":1},{"_time":88.0,"_type":0,"_value":3},{"_time":88.0,"_type":1,"_value":3},{"_time":88.0,"_type":2,"_value":1},{"_time":88.0,"_type":12,"_value":5},{"_time":88.0,"_type":13,"_value":5},{"_time":91.0,"_type":3,"_value":2},{"_time":92.0,"_type":2,"_value":6},{"_time":92.0,"_type":3,"_value":6},{"_time":92.0,"_type":4,"_value":6},{"_time":92.0,"_type":8,"_value":0},{"_time":96.0,"_type":0,"_value":3},{"_time":96.0,"_type":1,"_value":3},{"_time":96.0,"_type":2,"_value":1},{"_time":96.0,"_type":3,"_value":0},{"_time":96.0,"_type":4,"_value":1},{"_time":96.0,"_type":12,"_value":5},{"_time":96.0,"_type":13,"_value":5},{"_time":99.0,"_type":2,"_value":0},{"_time":99.0,"_type":4,"_value":6},{"_time":100.0,"_type":0,"_value":0},{"_time":100.0,"_type":1,"_value":0},{"_time":100.0,"_type":2,"_value":1},{"_time":100.0,"_type":4,"_value":1},{"_time":100.0,"_type":8,"_value":0},{"_time":100.0,"_type":12,"_value":0},{"_time":102.0,"_type":3,"_value":1},{"_time":102.0,"_type":13,"_value":0},{"_time":103.0,"_type":8,"_value":0},{"_time":104.0,"_type":0,"_value":2},{"_time":104.0,"_type":1,"_value":3},{"_time":104.0,"_type":2,"_value":2},{"_time":104.0,"_type":3,"_value":2},{"_time":104.0,"_type":4,"_value":2},{"_time":104.0,"_type":8,"_value":0},{"_time":104.0,"_type":9,"_value":1},{"_time":104.0,"_type":12,"_value":5},{"_time":104.0,"_type":13,"_value":5},{"_time":108.0,"_type":0,"_value":6},{"_time":108.0,"_type":1,"_value":7},{"_time":108.0,"_type":2,"_value":6},{"_time":108.0,"_type":3,"_value":6},{"_time":108.0,"_type":4,"_value":5},{"_time":112.0,"_type":0,"_value":2},{"_time":112.0,"_type":1,"_value":3},{"_time":112.0,"_type":2,"_value":2},{"_time":112.0,"_type":3,"_value":2},{"_time":112.0,"_type":4,"_value":1},{"_time":112.0,"_type":8,"_value":0},{"_time":112.0,"_type":12,"_value":5},{"_time":112.0,"_type":13,"_value":5},{"_time":116.0,"_type":0,"_value":6},{"_time":116.0,"_type":1,"_value":7},{"_time":116.0,"_type":2,"_value":6},{"_time":116.0,"_type":3,"_value":6},{"_time":116.0,"_type":4,"_value":5},{"_time":118.0,"_type":2,"_value":7},{"_time":118.0,"_type":3,"_value":7},{"_time":120.0,"_type":0,"_value":2},{"_time":120.0,"_type":1,"_value":0},{"_time":120.0,"_type":3,"_value":2},{"_time":120.0,"_type":4,"_value":1},{"_time":120.0,"_type":8,"_value":0},{"_time":120.0,"_type":12,"_value":5},{"_time":120.0,"_type":13,"_value":5},{"_time":121.0,"_type":2,"_value":2},{"_time":123.0,"_type":2,"_value":3},{"_time":123.0,"_type":3,"_value":3},{"_time":124.0,"_type":0,"_value":0},{"_time":124.0,"_type":1,"_value":6},{"_time":124.0,"_type":3,"_value":6},{"_time":124.0,"_type":4,"_value":5},{"_time":124.0,"_type":8,"_value":0},{"_time":125.0,"_type":2,"_value":6},{"_time":127.0,"_type":1,"_value":0},{"_time":128.0,"_type":2,"_value":0},{"_time":128.0,"_type":3,"_value":0},{"_time":128.0,"_type":4,"_value":1},{"_time":128.0,"_type":8,"_value":0},{"_time":128.0,"_type":9,"_value":0},{"_time":130.0,"_type":0,"_value":1},{"_time":132.0,"_type":0,"_value":0},{"_time":132.0,"_type":1,"_value":3},{"_time":132.0,"_type":8,"_value":0},{"_time":132.0,"_type":9,"_value":1},{"_time":133.0,"_type":0,"_value":3},{"_time":133.0,"_type":1,"_value":0},{"_time":134.0,"_type":2,"_value":0},{"_time":134.0,"_type":3,"_value":3},{"_time":134.0,"_type":13,"_value":0},{"_time":135.0,"_type":2,"_value":3},{"_time":135.0,"_type":3,"_value":0},{"_time":135.0,"_type":12,"_value":0},{"_time":136.0,"_type":0,"_value":7},{"_time":136.0,"_type":2,"_value":7},{"_time":136.0,"_type":3,"_value":7},{"_time":136.0,"_type":4,"_value":6},{"_time":136.0,"_type":8,"_value":0},{"_time":136.0,"_type":9,"_value":0},{"_time":144.0,"_type":1,"_value":3},{"_time":144.0,"_type":4,"_value":2},{"_time":144.0,"_type":8,"_value":0},{"_time":144.0,"_type":9,"_value":1},{"_time":152.0,"_type":0,"_value":7},{"_time":152.0,"_type":4,"_value":6},{"_time":152.0,"_type":8,"_value":0},{"_time":152.0,"_type":9,"_value":0},{"_time":160.0,"_type":1,"_value":3},{"_time":160.0,"_type":4,"_value":2},{"_time":160.0,"_type":8,"_value":0},{"_time":160.0,"_type":9,"_value":1},{"_time":168.0,"_type":0,"_value":7},{"_time":168.0,"_type":4,"_value":6},{"_time":168.0,"_type":8,"_value":0},{"_time":168.0,"_type":9,"_value":0},{"_time":176.0,"_type":1,"_value":3},{"_time":176.0,"_type":4,"_value":2},{"_time":176.0,"_type":8,"_value":0},{"_time":176.0,"_type":9,"_value":1},{"_time":184.0,"_type":0,"_value":2},{"_time":184.0,"_type":2,"_value":3},{"_time":184.0,"_type":3,"_value":3},{"_time":184.0,"_type":8,"_value":0},{"_time":184.0,"_type":9,"_value":0},{"_time":192.0,"_type":0,"_value":3},{"_time":192.0,"_type":2,"_value":3},{"_time":192.0,"_type":3,"_value":3},{"_time":192.0,"_type":4,"_value":2},{"_time":192.0,"_type":8,"_value":0},{"_time":192.0,"_type":9,"_value":1},{"_time":198.0,"_type":0,"_value":3},{"_time":198.0,"_type":1,"_value":0},{"_time":198.0,"_type":2,"_value":0},{"_time":198.0,"_type":3,"_value":0},{"_time":198.0,"_type":4,"_value":0},{"_time":198.5,"_type":1,"_value":3},{"_time":199.0,"_type":4,"_value":3},{"_time":200.0,"_type":0,"_value":3},{"_time":200.0,"_type":1,"_value":3},{"_time":200.0,"_type":2,"_value":2},{"_time":200.0,"_type":3,"_value":2},{"_time":200.0,"_type":4,"_value":3},{"_time":200.0,"_type":8,"_value":0},{"_time":200.0,"_type":9,"_value":1},{"_time":200.0,"_type":12,"_value":5},{"_time":200.0,"_type":13,"_value":5},{"_time":202.0,"_type":0,"_value":3},{"_time":202.0,"_type":1,"_value":3},{"_time":202.0,"_type":4,"_value":3},{"_time":204.0,"_type":2,"_value":2},{"_time":204.0,"_type":3,"_value":2},{"_time":204.0,"_type":8,"_value":0},{"_time":206.0,"_type":0,"_value":3},{"_time":206.0,"_type":4,"_value":3},{"_time":207.0,"_type":1,"_value":3},{"_time":208.0,"_type":0,"_value":3},{"_time":208.0,"_type":1,"_value":3},{"_time":208.0,"_type":4,"_value":3},{"_time":208.0,"_type":8,"_value":0},{"_time":208.0,"_type":12,"_value":5},{"_time":208.0,"_type":13,"_value":5},{"_time":210.0,"_type":0,"_value":3},{"_time":210.0,"_type":1,"_value":3},{"_time":210.0,"_type":4,"_value":3},{"_time":212.0,"_type":2,"_value":2},{"_time":212.0,"_type":3,"_value":2},{"_time":212.0,"_type":8,"_value":0},{"_time":214.0,"_type":1,"_value":3},{"_time":215.0,"_type":0,"_value":3},{"_time":215.0,"_type":4,"_value":3},{"_time":216.0,"_type":0,"_value":3},{"_time":216.0,"_type":1,"_value":3},{"_time":216.0,"_type":4,"_value":3},{"_time":216.0,"_type":8,"_value":0},{"_time":216.0,"_type":12,"_value":5},{"_time":216.0,"_type":13,"_value":5},{"_time":218.0,"_type":0,"_value":3},{"_time":218.0,"_type":1,"_value":3},{"_time":218.0,"_type":4,"_value":3},{"_time":220.0,"_type":2,"_value":2},{"_time":220.0,"_type":3,"_value":2},{"_time":220.0,"_type":8,"_value":0},{"_time":222.0,"_type":0,"_value":3},{"_time":223.0,"_type":1,"_value":3},{"_time":223.0,"_type":4,"_value":3},{"_time":224.0,"_type":0,"_value":3},{"_time":224.0,"_type":1,"_value":3},{"_time":224.0,"_type":4,"_value":3},{"_time":224.0,"_type":8,"_value":0},{"_time":224.0,"_type":12,"_value":5},{"_time":224.0,"_type":13,"_value":5},{"_time":226.0,"_type":0,"_value":3},{"_time":226.0,"_type":1,"_value":3},{"_time":226.0,"_type":4,"_value":3},{"_time":228.0,"_type":2,"_value":2},{"_time":228.0,"_type":3,"_value":2},{"_time":228.0,"_type":8,"_value":0},{"_time":230.0,"_type":1,"_value":3},{"_time":231.0,"_type":1,"_value":3},{"_time":232.0,"_type":0,"_value":3},{"_time":232.0,"_type":1,"_value":3},{"_time":232.0,"_type":4,"_value":2},{"_time":232.0,"_type":8,"_value":0},{"_time":232.0,"_type":12,"_value":5},{"_time":232.0,"_type":13,"_value":5},{"_time":234.0,"_type":1,"_value":3},{"_time":236.0,"_type":0,"_value":3},{"_time":236.0,"_type":8,"_value":0},{"_time":237.0,"_type":1,"_value":3},{"_time":238.0,"_type":1,"_value":3},{"_time":240.0,"_type":1,"_value":3},{"_time":240.0,"_type":4,"_value":2},{"_time":240.0,"_type":8,"_value":0},{"_time":240.0,"_type":12,"_value":6},{"_time":240.0,"_type":13,"_value":6},{"_time":242.0,"_type":0,"_value":3},{"_time":244.0,"_type":1,"_value":3},{"_time":244.0,"_type":8,"_value":0},{"_time":245.0,"_type":0,"_value":3},{"_time":246.0,"_type":1,"_value":3},{"_time":247.0,"_type":1,"_value":3},{"_time":249.0,"_type":0,"_value":3},{"_time":249.0,"_type":1,"_value":3},{"_time":249.0,"_type":2,"_value":2},{"_time":249.0,"_type":3,"_value":2},{"_time":249.0,"_type":4,"_value":2},{"_time":249.0,"_type":12,"_value":7},{"_time":249.0,"_type":13,"_value":7},{"_time":252.0,"_type":0,"_value":3},{"_time":252.0,"_type":8,"_value":0},{"_time":254.0,"_type":1,"_value":3},{"_time":256.0,"_type":0,"_value":3},{"_time":256.0,"_type":4,"_value":2},{"_time":256.0,"_type":8,"_value":0},{"_time":257.0,"_type":1,"_value":3},{"_time":258.0,"_type":0,"_value":3},{"_time":259.0,"_type":1,"_value":3},{"_time":260.0,"_type":0,"_value":3},{"_time":260.0,"_type":1,"_value":0},{"_time":260.0,"_type":2,"_value":0},{"_time":260.0,"_type":3,"_value":0},{"_time":260.0,"_type":4,"_value":3},{"_time":260.0,"_type":8,"_value":0},{"_time":260.0,"_type":12,"_value":0},{"_time":260.0,"_type":13,"_value":0},{"_time":261.0,"_type":2,"_value":3},{"_time":261.0,"_type":3,"_value":3},{"_time":262.0,"_type":0,"_value":7},{"_time":262.0,"_type":4,"_value":7},{"_time":263.0,"_type":1,"_value":7},{"_time":264.0,"_type":0,"_value":2},{"_time":264.0,"_type":1,"_value":3},{"_time":264.0,"_type":2,"_value":2},{"_time":264.0,"_type":3,"_value":2},{"_time":264.0,"_type":4,"_value":3},{"_time":264.0,"_type":8,"_value":0},{"_time":264.0,"_type":9,"_value":0},{"_time":272.0,"_type":0,"_value":7},{"_time":272.0,"_type":1,"_value":6},{"_time":272.0,"_type":2,"_value":0},{"_time":272.0,"_type":3,"_value":0},{"_time":272.0,"_type":4,"_value":6},{"_time":272.0,"_type":8,"_value":0},{"_time":272.0,"_type":9,"_value":1},{"_time":280.0,"_type":0,"_value":2},{"_time":280.0,"_type":1,"_value":3},{"_time":280.0,"_type":2,"_value":2},{"_time":280.0,"_type":3,"_value":2},{"_time":280.0,"_type":4,"_value":3},{"_time":280.0,"_type":8,"_value":0},{"_time":280.0,"_type":9,"_value":0},{"_time":288.0,"_type":0,"_value":6},{"_time":288.0,"_type":1,"_value":6},{"_time":288.0,"_type":2,"_value":0},{"_time":288.0,"_type":3,"_value":0},{"_time":288.0,"_type":4,"_value":0},{"_time":288.0,"_type":8,"_value":0},{"_time":288.0,"_type":9,"_value":1},{"_time":296.0,"_type":0,"_value":7},{"_time":296.0,"_type":1,"_value":7},{"_time":296.0,"_type":2,"_value":7},{"_time":296.0,"_type":3,"_value":7},{"_time":296.0,"_type":4,"_value":6},{"_time":296.0,"_type":8,"_value":0},{"_time":296.0,"_type":9,"_value":0}],"_notes":[{"_time":8.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":14.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":16.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":24.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":30.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":32.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":36.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":40.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":48.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":52.0,"_lineIndex":3,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":56.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":62.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":64.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":68.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":72.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":75.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":76.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":79.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":80.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":83.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":84.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":88.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":91.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":92.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":95.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":96.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":99.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":100.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":104.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":107.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":108.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":111.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":112.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":115.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":116.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":120.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":123.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":124.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":127.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":128.0,"_lineIndex":3,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":132.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":134.0,"_lineIndex":0,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":136.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":136.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":144.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":144.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":152.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":152.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":160.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":160.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":168.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":168.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":8},{"_time":176.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":176.0,"_lineIndex":0,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":184.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":184.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":192.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":192.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":200.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":202.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":206.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":208.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":210.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":214.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":216.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":218.0,"_lineIndex":3,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":222.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":224.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":226.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":230.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":232.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":234.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":236.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":238.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":240.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":242.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":244.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":248.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":250.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":252.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":254.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":256.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":260.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":262.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":264.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":264.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":272.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":272.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":280.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":280.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":288.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":288.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":296.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":296.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8}],"_obstacles":[{"_time":72.0,"_lineIndex":3,"_type":0,"_duration":8.0,"_width":1},{"_time":88.0,"_lineIndex":0,"_type":0,"_duration":8.0,"_width":1},{"_time":168.0,"_lineIndex":0,"_type":0,"_duration":2.0,"_width":1},{"_time":170.0,"_lineIndex":1,"_type":0,"_duration":2.0,"_width":1},{"_time":176.0,"_lineIndex":3,"_type":0,"_duration":2.0,"_width":1},{"_time":178.0,"_lineIndex":2,"_type":0,"_duration":2.0,"_width":1},{"_time":186.0,"_lineIndex":0,"_type":1,"_duration":2.0,"_width":4}]} -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/NoArrowsNormal.dat: -------------------------------------------------------------------------------- 1 | {"_version":"2.0.0","_events":[{"_time":0.0,"_type":4,"_value":5},{"_time":8.0,"_type":0,"_value":2},{"_time":8.0,"_type":4,"_value":2},{"_time":16.0,"_type":0,"_value":0},{"_time":16.0,"_type":4,"_value":5},{"_time":24.0,"_type":1,"_value":2},{"_time":24.0,"_type":4,"_value":1},{"_time":32.0,"_type":1,"_value":0},{"_time":32.0,"_type":4,"_value":5},{"_time":40.0,"_type":0,"_value":2},{"_time":40.0,"_type":1,"_value":2},{"_time":40.0,"_type":4,"_value":1},{"_time":40.0,"_type":8,"_value":0},{"_time":48.0,"_type":0,"_value":0},{"_time":48.0,"_type":1,"_value":0},{"_time":48.0,"_type":2,"_value":2},{"_time":48.0,"_type":8,"_value":0},{"_time":52.0,"_type":2,"_value":0},{"_time":52.0,"_type":3,"_value":2},{"_time":52.0,"_type":8,"_value":0},{"_time":56.0,"_type":2,"_value":2},{"_time":56.0,"_type":3,"_value":2},{"_time":56.0,"_type":4,"_value":2},{"_time":56.0,"_type":8,"_value":0},{"_time":56.0,"_type":9,"_value":1},{"_time":64.0,"_type":1,"_value":2},{"_time":64.0,"_type":2,"_value":2},{"_time":64.0,"_type":3,"_value":2},{"_time":64.0,"_type":4,"_value":2},{"_time":64.0,"_type":8,"_value":0},{"_time":64.0,"_type":9,"_value":0},{"_time":68.0,"_type":0,"_value":3},{"_time":68.0,"_type":1,"_value":3},{"_time":68.0,"_type":2,"_value":3},{"_time":68.0,"_type":3,"_value":3},{"_time":68.0,"_type":4,"_value":5},{"_time":72.0,"_type":0,"_value":3},{"_time":72.0,"_type":1,"_value":3},{"_time":72.0,"_type":2,"_value":2},{"_time":72.0,"_type":3,"_value":2},{"_time":72.0,"_type":4,"_value":2},{"_time":72.0,"_type":8,"_value":0},{"_time":72.0,"_type":9,"_value":1},{"_time":72.0,"_type":12,"_value":5},{"_time":72.0,"_type":13,"_value":5},{"_time":75.0,"_type":3,"_value":2},{"_time":76.0,"_type":2,"_value":6},{"_time":76.0,"_type":3,"_value":6},{"_time":76.0,"_type":4,"_value":6},{"_time":76.0,"_type":8,"_value":0},{"_time":79.0,"_type":3,"_value":6},{"_time":80.0,"_type":0,"_value":3},{"_time":80.0,"_type":1,"_value":3},{"_time":80.0,"_type":2,"_value":2},{"_time":80.0,"_type":3,"_value":0},{"_time":80.0,"_type":4,"_value":1},{"_time":80.0,"_type":12,"_value":5},{"_time":80.0,"_type":13,"_value":5},{"_time":83.0,"_type":3,"_value":2},{"_time":84.0,"_type":2,"_value":2},{"_time":84.0,"_type":8,"_value":0},{"_time":86.0,"_type":3,"_value":1},{"_time":88.0,"_type":0,"_value":3},{"_time":88.0,"_type":1,"_value":3},{"_time":88.0,"_type":2,"_value":1},{"_time":88.0,"_type":12,"_value":5},{"_time":88.0,"_type":13,"_value":5},{"_time":91.0,"_type":3,"_value":2},{"_time":92.0,"_type":2,"_value":6},{"_time":92.0,"_type":3,"_value":6},{"_time":92.0,"_type":4,"_value":6},{"_time":92.0,"_type":8,"_value":0},{"_time":96.0,"_type":0,"_value":3},{"_time":96.0,"_type":1,"_value":3},{"_time":96.0,"_type":2,"_value":1},{"_time":96.0,"_type":3,"_value":0},{"_time":96.0,"_type":4,"_value":1},{"_time":96.0,"_type":12,"_value":5},{"_time":96.0,"_type":13,"_value":5},{"_time":99.0,"_type":2,"_value":0},{"_time":99.0,"_type":4,"_value":6},{"_time":100.0,"_type":0,"_value":0},{"_time":100.0,"_type":1,"_value":0},{"_time":100.0,"_type":2,"_value":1},{"_time":100.0,"_type":4,"_value":1},{"_time":100.0,"_type":8,"_value":0},{"_time":100.0,"_type":12,"_value":0},{"_time":102.0,"_type":3,"_value":1},{"_time":102.0,"_type":13,"_value":0},{"_time":103.0,"_type":8,"_value":0},{"_time":104.0,"_type":0,"_value":2},{"_time":104.0,"_type":1,"_value":3},{"_time":104.0,"_type":2,"_value":2},{"_time":104.0,"_type":3,"_value":2},{"_time":104.0,"_type":4,"_value":2},{"_time":104.0,"_type":8,"_value":0},{"_time":104.0,"_type":9,"_value":1},{"_time":104.0,"_type":12,"_value":5},{"_time":104.0,"_type":13,"_value":5},{"_time":108.0,"_type":0,"_value":6},{"_time":108.0,"_type":1,"_value":7},{"_time":108.0,"_type":2,"_value":6},{"_time":108.0,"_type":3,"_value":6},{"_time":108.0,"_type":4,"_value":5},{"_time":112.0,"_type":0,"_value":2},{"_time":112.0,"_type":1,"_value":3},{"_time":112.0,"_type":2,"_value":2},{"_time":112.0,"_type":3,"_value":2},{"_time":112.0,"_type":4,"_value":1},{"_time":112.0,"_type":8,"_value":0},{"_time":112.0,"_type":12,"_value":5},{"_time":112.0,"_type":13,"_value":5},{"_time":116.0,"_type":0,"_value":6},{"_time":116.0,"_type":1,"_value":7},{"_time":116.0,"_type":2,"_value":6},{"_time":116.0,"_type":3,"_value":6},{"_time":116.0,"_type":4,"_value":5},{"_time":118.0,"_type":2,"_value":7},{"_time":118.0,"_type":3,"_value":7},{"_time":120.0,"_type":0,"_value":2},{"_time":120.0,"_type":1,"_value":0},{"_time":120.0,"_type":3,"_value":2},{"_time":120.0,"_type":4,"_value":1},{"_time":120.0,"_type":8,"_value":0},{"_time":120.0,"_type":12,"_value":5},{"_time":120.0,"_type":13,"_value":5},{"_time":121.0,"_type":2,"_value":2},{"_time":123.0,"_type":2,"_value":3},{"_time":123.0,"_type":3,"_value":3},{"_time":124.0,"_type":0,"_value":0},{"_time":124.0,"_type":1,"_value":6},{"_time":124.0,"_type":3,"_value":6},{"_time":124.0,"_type":4,"_value":5},{"_time":124.0,"_type":8,"_value":0},{"_time":125.0,"_type":2,"_value":6},{"_time":127.0,"_type":1,"_value":0},{"_time":128.0,"_type":2,"_value":0},{"_time":128.0,"_type":3,"_value":0},{"_time":128.0,"_type":4,"_value":1},{"_time":128.0,"_type":8,"_value":0},{"_time":128.0,"_type":9,"_value":0},{"_time":130.0,"_type":0,"_value":1},{"_time":132.0,"_type":0,"_value":0},{"_time":132.0,"_type":1,"_value":3},{"_time":132.0,"_type":8,"_value":0},{"_time":132.0,"_type":9,"_value":1},{"_time":133.0,"_type":0,"_value":3},{"_time":133.0,"_type":1,"_value":0},{"_time":134.0,"_type":2,"_value":0},{"_time":134.0,"_type":3,"_value":3},{"_time":134.0,"_type":13,"_value":0},{"_time":135.0,"_type":2,"_value":3},{"_time":135.0,"_type":3,"_value":0},{"_time":135.0,"_type":12,"_value":0},{"_time":136.0,"_type":0,"_value":7},{"_time":136.0,"_type":2,"_value":7},{"_time":136.0,"_type":3,"_value":7},{"_time":136.0,"_type":4,"_value":6},{"_time":136.0,"_type":8,"_value":0},{"_time":136.0,"_type":9,"_value":0},{"_time":144.0,"_type":1,"_value":3},{"_time":144.0,"_type":4,"_value":2},{"_time":144.0,"_type":8,"_value":0},{"_time":144.0,"_type":9,"_value":1},{"_time":152.0,"_type":0,"_value":7},{"_time":152.0,"_type":4,"_value":6},{"_time":152.0,"_type":8,"_value":0},{"_time":152.0,"_type":9,"_value":0},{"_time":160.0,"_type":1,"_value":3},{"_time":160.0,"_type":4,"_value":2},{"_time":160.0,"_type":8,"_value":0},{"_time":160.0,"_type":9,"_value":1},{"_time":168.0,"_type":0,"_value":7},{"_time":168.0,"_type":4,"_value":6},{"_time":168.0,"_type":8,"_value":0},{"_time":168.0,"_type":9,"_value":0},{"_time":176.0,"_type":1,"_value":3},{"_time":176.0,"_type":4,"_value":2},{"_time":176.0,"_type":8,"_value":0},{"_time":176.0,"_type":9,"_value":1},{"_time":184.0,"_type":0,"_value":2},{"_time":184.0,"_type":2,"_value":3},{"_time":184.0,"_type":3,"_value":3},{"_time":184.0,"_type":8,"_value":0},{"_time":184.0,"_type":9,"_value":0},{"_time":192.0,"_type":0,"_value":3},{"_time":192.0,"_type":2,"_value":3},{"_time":192.0,"_type":3,"_value":3},{"_time":192.0,"_type":4,"_value":2},{"_time":192.0,"_type":8,"_value":0},{"_time":192.0,"_type":9,"_value":1},{"_time":198.0,"_type":0,"_value":3},{"_time":198.0,"_type":1,"_value":0},{"_time":198.0,"_type":2,"_value":0},{"_time":198.0,"_type":3,"_value":0},{"_time":198.0,"_type":4,"_value":0},{"_time":198.5,"_type":1,"_value":3},{"_time":199.0,"_type":4,"_value":3},{"_time":200.0,"_type":0,"_value":3},{"_time":200.0,"_type":1,"_value":3},{"_time":200.0,"_type":2,"_value":2},{"_time":200.0,"_type":3,"_value":2},{"_time":200.0,"_type":4,"_value":3},{"_time":200.0,"_type":8,"_value":0},{"_time":200.0,"_type":9,"_value":1},{"_time":200.0,"_type":12,"_value":5},{"_time":200.0,"_type":13,"_value":5},{"_time":202.0,"_type":0,"_value":3},{"_time":202.0,"_type":1,"_value":3},{"_time":202.0,"_type":4,"_value":3},{"_time":204.0,"_type":2,"_value":2},{"_time":204.0,"_type":3,"_value":2},{"_time":204.0,"_type":8,"_value":0},{"_time":206.0,"_type":0,"_value":3},{"_time":206.0,"_type":4,"_value":3},{"_time":207.0,"_type":1,"_value":3},{"_time":208.0,"_type":0,"_value":3},{"_time":208.0,"_type":1,"_value":3},{"_time":208.0,"_type":4,"_value":3},{"_time":208.0,"_type":8,"_value":0},{"_time":208.0,"_type":12,"_value":5},{"_time":208.0,"_type":13,"_value":5},{"_time":210.0,"_type":0,"_value":3},{"_time":210.0,"_type":1,"_value":3},{"_time":210.0,"_type":4,"_value":3},{"_time":212.0,"_type":2,"_value":2},{"_time":212.0,"_type":3,"_value":2},{"_time":212.0,"_type":8,"_value":0},{"_time":214.0,"_type":1,"_value":3},{"_time":215.0,"_type":0,"_value":3},{"_time":215.0,"_type":4,"_value":3},{"_time":216.0,"_type":0,"_value":3},{"_time":216.0,"_type":1,"_value":3},{"_time":216.0,"_type":4,"_value":3},{"_time":216.0,"_type":8,"_value":0},{"_time":216.0,"_type":12,"_value":5},{"_time":216.0,"_type":13,"_value":5},{"_time":218.0,"_type":0,"_value":3},{"_time":218.0,"_type":1,"_value":3},{"_time":218.0,"_type":4,"_value":3},{"_time":220.0,"_type":2,"_value":2},{"_time":220.0,"_type":3,"_value":2},{"_time":220.0,"_type":8,"_value":0},{"_time":222.0,"_type":0,"_value":3},{"_time":223.0,"_type":1,"_value":3},{"_time":223.0,"_type":4,"_value":3},{"_time":224.0,"_type":0,"_value":3},{"_time":224.0,"_type":1,"_value":3},{"_time":224.0,"_type":4,"_value":3},{"_time":224.0,"_type":8,"_value":0},{"_time":224.0,"_type":12,"_value":5},{"_time":224.0,"_type":13,"_value":5},{"_time":226.0,"_type":0,"_value":3},{"_time":226.0,"_type":1,"_value":3},{"_time":226.0,"_type":4,"_value":3},{"_time":228.0,"_type":2,"_value":2},{"_time":228.0,"_type":3,"_value":2},{"_time":228.0,"_type":8,"_value":0},{"_time":230.0,"_type":1,"_value":3},{"_time":231.0,"_type":1,"_value":3},{"_time":232.0,"_type":0,"_value":3},{"_time":232.0,"_type":1,"_value":3},{"_time":232.0,"_type":4,"_value":2},{"_time":232.0,"_type":8,"_value":0},{"_time":232.0,"_type":12,"_value":5},{"_time":232.0,"_type":13,"_value":5},{"_time":234.0,"_type":1,"_value":3},{"_time":236.0,"_type":0,"_value":3},{"_time":236.0,"_type":8,"_value":0},{"_time":237.0,"_type":1,"_value":3},{"_time":238.0,"_type":1,"_value":3},{"_time":240.0,"_type":1,"_value":3},{"_time":240.0,"_type":4,"_value":2},{"_time":240.0,"_type":8,"_value":0},{"_time":240.0,"_type":12,"_value":6},{"_time":240.0,"_type":13,"_value":6},{"_time":242.0,"_type":0,"_value":3},{"_time":244.0,"_type":1,"_value":3},{"_time":244.0,"_type":8,"_value":0},{"_time":245.0,"_type":0,"_value":3},{"_time":246.0,"_type":1,"_value":3},{"_time":247.0,"_type":1,"_value":3},{"_time":249.0,"_type":0,"_value":3},{"_time":249.0,"_type":1,"_value":3},{"_time":249.0,"_type":2,"_value":2},{"_time":249.0,"_type":3,"_value":2},{"_time":249.0,"_type":4,"_value":2},{"_time":249.0,"_type":12,"_value":7},{"_time":249.0,"_type":13,"_value":7},{"_time":252.0,"_type":0,"_value":3},{"_time":252.0,"_type":8,"_value":0},{"_time":254.0,"_type":1,"_value":3},{"_time":256.0,"_type":0,"_value":3},{"_time":256.0,"_type":4,"_value":2},{"_time":256.0,"_type":8,"_value":0},{"_time":257.0,"_type":1,"_value":3},{"_time":258.0,"_type":0,"_value":3},{"_time":259.0,"_type":1,"_value":3},{"_time":260.0,"_type":0,"_value":3},{"_time":260.0,"_type":1,"_value":0},{"_time":260.0,"_type":2,"_value":0},{"_time":260.0,"_type":3,"_value":0},{"_time":260.0,"_type":4,"_value":3},{"_time":260.0,"_type":8,"_value":0},{"_time":260.0,"_type":12,"_value":0},{"_time":260.0,"_type":13,"_value":0},{"_time":261.0,"_type":2,"_value":3},{"_time":261.0,"_type":3,"_value":3},{"_time":262.0,"_type":0,"_value":7},{"_time":262.0,"_type":4,"_value":7},{"_time":263.0,"_type":1,"_value":7},{"_time":264.0,"_type":0,"_value":2},{"_time":264.0,"_type":1,"_value":3},{"_time":264.0,"_type":2,"_value":2},{"_time":264.0,"_type":3,"_value":2},{"_time":264.0,"_type":4,"_value":3},{"_time":264.0,"_type":8,"_value":0},{"_time":264.0,"_type":9,"_value":0},{"_time":272.0,"_type":0,"_value":7},{"_time":272.0,"_type":1,"_value":6},{"_time":272.0,"_type":2,"_value":0},{"_time":272.0,"_type":3,"_value":0},{"_time":272.0,"_type":4,"_value":6},{"_time":272.0,"_type":8,"_value":0},{"_time":272.0,"_type":9,"_value":1},{"_time":280.0,"_type":0,"_value":2},{"_time":280.0,"_type":1,"_value":3},{"_time":280.0,"_type":2,"_value":2},{"_time":280.0,"_type":3,"_value":2},{"_time":280.0,"_type":4,"_value":3},{"_time":280.0,"_type":8,"_value":0},{"_time":280.0,"_type":9,"_value":0},{"_time":288.0,"_type":0,"_value":6},{"_time":288.0,"_type":1,"_value":6},{"_time":288.0,"_type":2,"_value":0},{"_time":288.0,"_type":3,"_value":0},{"_time":288.0,"_type":4,"_value":0},{"_time":288.0,"_type":8,"_value":0},{"_time":288.0,"_type":9,"_value":1},{"_time":296.0,"_type":0,"_value":7},{"_time":296.0,"_type":1,"_value":7},{"_time":296.0,"_type":2,"_value":7},{"_time":296.0,"_type":3,"_value":7},{"_time":296.0,"_type":4,"_value":6},{"_time":296.0,"_type":8,"_value":0},{"_time":296.0,"_type":9,"_value":0}],"_notes":[{"_time":8.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":14.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":16.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":24.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":30.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":32.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":36.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":40.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":46.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":48.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":52.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":56.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":62.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":64.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":68.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":72.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":75.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":76.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":79.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":80.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":83.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":84.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":86.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":88.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":91.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":92.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":95.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":96.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":99.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":100.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":102.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":104.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":106.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":108.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":110.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":112.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":114.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":116.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":118.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":120.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":121.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":123.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":124.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":125.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":127.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":128.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":130.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":132.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":133.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":134.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":135.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":136.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":136.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":144.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":144.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":152.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":152.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":160.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":160.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":168.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":168.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":176.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":176.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":184.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":184.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":192.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":192.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":200.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":202.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":206.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":207.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":208.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":210.0,"_lineIndex":3,"_lineLayer":1,"_type":0,"_cutDirection":8},{"_time":214.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":215.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":216.0,"_lineIndex":0,"_lineLayer":1,"_type":1,"_cutDirection":8},{"_time":218.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":8},{"_time":222.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":223.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":224.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":226.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":230.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":231.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":232.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":234.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":236.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":237.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":238.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":240.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":242.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":244.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":245.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":246.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":247.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":249.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":250.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":252.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":254.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":256.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":257.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":258.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":259.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":260.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":261.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":262.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":263.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":264.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":264.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":272.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":272.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":280.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":280.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":288.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":8},{"_time":288.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":296.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":8},{"_time":296.0,"_lineIndex":3,"_lineLayer":0,"_type":0,"_cutDirection":8}],"_obstacles":[{"_time":72.0,"_lineIndex":3,"_type":0,"_duration":8.0,"_width":1},{"_time":88.0,"_lineIndex":0,"_type":0,"_duration":8.0,"_width":1},{"_time":168.0,"_lineIndex":0,"_type":0,"_duration":2.0,"_width":1},{"_time":170.0,"_lineIndex":1,"_type":0,"_duration":2.0,"_width":1},{"_time":176.0,"_lineIndex":3,"_type":0,"_duration":2.0,"_width":1},{"_time":178.0,"_lineIndex":2,"_type":0,"_duration":2.0,"_width":1},{"_time":184.0,"_lineIndex":0,"_type":1,"_duration":12.0,"_width":4}]} -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/Normal.dat: -------------------------------------------------------------------------------- 1 | {"_version":"2.0.0","_events":[{"_time":0.0,"_type":4,"_value":5},{"_time":8.0,"_type":0,"_value":2},{"_time":8.0,"_type":4,"_value":2},{"_time":16.0,"_type":0,"_value":0},{"_time":16.0,"_type":4,"_value":5},{"_time":24.0,"_type":1,"_value":2},{"_time":24.0,"_type":4,"_value":1},{"_time":32.0,"_type":1,"_value":0},{"_time":32.0,"_type":4,"_value":5},{"_time":40.0,"_type":0,"_value":2},{"_time":40.0,"_type":1,"_value":2},{"_time":40.0,"_type":4,"_value":1},{"_time":40.0,"_type":8,"_value":0},{"_time":48.0,"_type":0,"_value":0},{"_time":48.0,"_type":1,"_value":0},{"_time":48.0,"_type":2,"_value":2},{"_time":48.0,"_type":8,"_value":0},{"_time":52.0,"_type":2,"_value":0},{"_time":52.0,"_type":3,"_value":2},{"_time":52.0,"_type":8,"_value":0},{"_time":56.0,"_type":2,"_value":2},{"_time":56.0,"_type":3,"_value":2},{"_time":56.0,"_type":4,"_value":2},{"_time":56.0,"_type":8,"_value":0},{"_time":56.0,"_type":9,"_value":1},{"_time":64.0,"_type":1,"_value":2},{"_time":64.0,"_type":2,"_value":2},{"_time":64.0,"_type":3,"_value":2},{"_time":64.0,"_type":4,"_value":2},{"_time":64.0,"_type":8,"_value":0},{"_time":64.0,"_type":9,"_value":0},{"_time":68.0,"_type":0,"_value":3},{"_time":68.0,"_type":1,"_value":3},{"_time":68.0,"_type":2,"_value":3},{"_time":68.0,"_type":3,"_value":3},{"_time":68.0,"_type":4,"_value":5},{"_time":72.0,"_type":0,"_value":3},{"_time":72.0,"_type":1,"_value":3},{"_time":72.0,"_type":2,"_value":2},{"_time":72.0,"_type":3,"_value":2},{"_time":72.0,"_type":4,"_value":2},{"_time":72.0,"_type":8,"_value":0},{"_time":72.0,"_type":9,"_value":1},{"_time":72.0,"_type":12,"_value":5},{"_time":72.0,"_type":13,"_value":5},{"_time":75.0,"_type":3,"_value":2},{"_time":76.0,"_type":2,"_value":6},{"_time":76.0,"_type":3,"_value":6},{"_time":76.0,"_type":4,"_value":6},{"_time":76.0,"_type":8,"_value":0},{"_time":79.0,"_type":3,"_value":6},{"_time":80.0,"_type":0,"_value":3},{"_time":80.0,"_type":1,"_value":3},{"_time":80.0,"_type":2,"_value":2},{"_time":80.0,"_type":3,"_value":0},{"_time":80.0,"_type":4,"_value":1},{"_time":80.0,"_type":12,"_value":5},{"_time":80.0,"_type":13,"_value":5},{"_time":83.0,"_type":3,"_value":2},{"_time":84.0,"_type":2,"_value":2},{"_time":84.0,"_type":8,"_value":0},{"_time":86.0,"_type":3,"_value":1},{"_time":88.0,"_type":0,"_value":3},{"_time":88.0,"_type":1,"_value":3},{"_time":88.0,"_type":2,"_value":1},{"_time":88.0,"_type":12,"_value":5},{"_time":88.0,"_type":13,"_value":5},{"_time":91.0,"_type":3,"_value":2},{"_time":92.0,"_type":2,"_value":6},{"_time":92.0,"_type":3,"_value":6},{"_time":92.0,"_type":4,"_value":6},{"_time":92.0,"_type":8,"_value":0},{"_time":96.0,"_type":0,"_value":3},{"_time":96.0,"_type":1,"_value":3},{"_time":96.0,"_type":2,"_value":1},{"_time":96.0,"_type":3,"_value":0},{"_time":96.0,"_type":4,"_value":1},{"_time":96.0,"_type":12,"_value":5},{"_time":96.0,"_type":13,"_value":5},{"_time":99.0,"_type":2,"_value":0},{"_time":99.0,"_type":4,"_value":6},{"_time":100.0,"_type":0,"_value":0},{"_time":100.0,"_type":1,"_value":0},{"_time":100.0,"_type":2,"_value":1},{"_time":100.0,"_type":4,"_value":1},{"_time":100.0,"_type":8,"_value":0},{"_time":100.0,"_type":12,"_value":0},{"_time":102.0,"_type":3,"_value":1},{"_time":102.0,"_type":13,"_value":0},{"_time":103.0,"_type":8,"_value":0},{"_time":104.0,"_type":0,"_value":2},{"_time":104.0,"_type":1,"_value":3},{"_time":104.0,"_type":2,"_value":2},{"_time":104.0,"_type":3,"_value":2},{"_time":104.0,"_type":4,"_value":2},{"_time":104.0,"_type":8,"_value":0},{"_time":104.0,"_type":9,"_value":1},{"_time":104.0,"_type":12,"_value":5},{"_time":104.0,"_type":13,"_value":5},{"_time":108.0,"_type":0,"_value":6},{"_time":108.0,"_type":1,"_value":7},{"_time":108.0,"_type":2,"_value":6},{"_time":108.0,"_type":3,"_value":6},{"_time":108.0,"_type":4,"_value":5},{"_time":112.0,"_type":0,"_value":2},{"_time":112.0,"_type":1,"_value":3},{"_time":112.0,"_type":2,"_value":2},{"_time":112.0,"_type":3,"_value":2},{"_time":112.0,"_type":4,"_value":1},{"_time":112.0,"_type":8,"_value":0},{"_time":112.0,"_type":12,"_value":5},{"_time":112.0,"_type":13,"_value":5},{"_time":116.0,"_type":0,"_value":6},{"_time":116.0,"_type":1,"_value":7},{"_time":116.0,"_type":2,"_value":6},{"_time":116.0,"_type":3,"_value":6},{"_time":116.0,"_type":4,"_value":5},{"_time":118.0,"_type":2,"_value":7},{"_time":118.0,"_type":3,"_value":7},{"_time":120.0,"_type":0,"_value":2},{"_time":120.0,"_type":1,"_value":0},{"_time":120.0,"_type":3,"_value":2},{"_time":120.0,"_type":4,"_value":1},{"_time":120.0,"_type":8,"_value":0},{"_time":120.0,"_type":12,"_value":5},{"_time":120.0,"_type":13,"_value":5},{"_time":121.0,"_type":2,"_value":2},{"_time":123.0,"_type":2,"_value":3},{"_time":123.0,"_type":3,"_value":3},{"_time":124.0,"_type":0,"_value":0},{"_time":124.0,"_type":1,"_value":6},{"_time":124.0,"_type":3,"_value":6},{"_time":124.0,"_type":4,"_value":5},{"_time":124.0,"_type":8,"_value":0},{"_time":125.0,"_type":2,"_value":6},{"_time":127.0,"_type":1,"_value":0},{"_time":128.0,"_type":2,"_value":0},{"_time":128.0,"_type":3,"_value":0},{"_time":128.0,"_type":4,"_value":1},{"_time":128.0,"_type":8,"_value":0},{"_time":128.0,"_type":9,"_value":0},{"_time":130.0,"_type":0,"_value":1},{"_time":132.0,"_type":0,"_value":0},{"_time":132.0,"_type":1,"_value":3},{"_time":132.0,"_type":8,"_value":0},{"_time":132.0,"_type":9,"_value":1},{"_time":133.0,"_type":0,"_value":3},{"_time":133.0,"_type":1,"_value":0},{"_time":134.0,"_type":2,"_value":0},{"_time":134.0,"_type":3,"_value":3},{"_time":134.0,"_type":13,"_value":0},{"_time":135.0,"_type":2,"_value":3},{"_time":135.0,"_type":3,"_value":0},{"_time":135.0,"_type":12,"_value":0},{"_time":136.0,"_type":0,"_value":7},{"_time":136.0,"_type":2,"_value":7},{"_time":136.0,"_type":3,"_value":7},{"_time":136.0,"_type":4,"_value":6},{"_time":136.0,"_type":8,"_value":0},{"_time":136.0,"_type":9,"_value":0},{"_time":144.0,"_type":1,"_value":3},{"_time":144.0,"_type":4,"_value":2},{"_time":144.0,"_type":8,"_value":0},{"_time":144.0,"_type":9,"_value":1},{"_time":152.0,"_type":0,"_value":7},{"_time":152.0,"_type":4,"_value":6},{"_time":152.0,"_type":8,"_value":0},{"_time":152.0,"_type":9,"_value":0},{"_time":160.0,"_type":1,"_value":3},{"_time":160.0,"_type":4,"_value":2},{"_time":160.0,"_type":8,"_value":0},{"_time":160.0,"_type":9,"_value":1},{"_time":168.0,"_type":0,"_value":7},{"_time":168.0,"_type":4,"_value":6},{"_time":168.0,"_type":8,"_value":0},{"_time":168.0,"_type":9,"_value":0},{"_time":176.0,"_type":1,"_value":3},{"_time":176.0,"_type":4,"_value":2},{"_time":176.0,"_type":8,"_value":0},{"_time":176.0,"_type":9,"_value":1},{"_time":184.0,"_type":0,"_value":2},{"_time":184.0,"_type":2,"_value":3},{"_time":184.0,"_type":3,"_value":3},{"_time":184.0,"_type":8,"_value":0},{"_time":184.0,"_type":9,"_value":0},{"_time":192.0,"_type":0,"_value":3},{"_time":192.0,"_type":2,"_value":3},{"_time":192.0,"_type":3,"_value":3},{"_time":192.0,"_type":4,"_value":2},{"_time":192.0,"_type":8,"_value":0},{"_time":192.0,"_type":9,"_value":1},{"_time":198.0,"_type":0,"_value":3},{"_time":198.0,"_type":1,"_value":0},{"_time":198.0,"_type":2,"_value":0},{"_time":198.0,"_type":3,"_value":0},{"_time":198.0,"_type":4,"_value":0},{"_time":198.5,"_type":1,"_value":3},{"_time":199.0,"_type":4,"_value":3},{"_time":200.0,"_type":0,"_value":3},{"_time":200.0,"_type":1,"_value":3},{"_time":200.0,"_type":2,"_value":2},{"_time":200.0,"_type":3,"_value":2},{"_time":200.0,"_type":4,"_value":3},{"_time":200.0,"_type":8,"_value":0},{"_time":200.0,"_type":9,"_value":1},{"_time":200.0,"_type":12,"_value":5},{"_time":200.0,"_type":13,"_value":5},{"_time":202.0,"_type":0,"_value":3},{"_time":202.0,"_type":1,"_value":3},{"_time":202.0,"_type":4,"_value":3},{"_time":204.0,"_type":2,"_value":2},{"_time":204.0,"_type":3,"_value":2},{"_time":204.0,"_type":8,"_value":0},{"_time":206.0,"_type":0,"_value":3},{"_time":206.0,"_type":4,"_value":3},{"_time":207.0,"_type":1,"_value":3},{"_time":208.0,"_type":0,"_value":3},{"_time":208.0,"_type":1,"_value":3},{"_time":208.0,"_type":4,"_value":3},{"_time":208.0,"_type":8,"_value":0},{"_time":208.0,"_type":12,"_value":5},{"_time":208.0,"_type":13,"_value":5},{"_time":210.0,"_type":0,"_value":3},{"_time":210.0,"_type":1,"_value":3},{"_time":210.0,"_type":4,"_value":3},{"_time":212.0,"_type":2,"_value":2},{"_time":212.0,"_type":3,"_value":2},{"_time":212.0,"_type":8,"_value":0},{"_time":214.0,"_type":1,"_value":3},{"_time":215.0,"_type":0,"_value":3},{"_time":215.0,"_type":4,"_value":3},{"_time":216.0,"_type":0,"_value":3},{"_time":216.0,"_type":1,"_value":3},{"_time":216.0,"_type":4,"_value":3},{"_time":216.0,"_type":8,"_value":0},{"_time":216.0,"_type":12,"_value":5},{"_time":216.0,"_type":13,"_value":5},{"_time":218.0,"_type":0,"_value":3},{"_time":218.0,"_type":1,"_value":3},{"_time":218.0,"_type":4,"_value":3},{"_time":220.0,"_type":2,"_value":2},{"_time":220.0,"_type":3,"_value":2},{"_time":220.0,"_type":8,"_value":0},{"_time":222.0,"_type":0,"_value":3},{"_time":223.0,"_type":1,"_value":3},{"_time":223.0,"_type":4,"_value":3},{"_time":224.0,"_type":0,"_value":3},{"_time":224.0,"_type":1,"_value":3},{"_time":224.0,"_type":4,"_value":3},{"_time":224.0,"_type":8,"_value":0},{"_time":224.0,"_type":12,"_value":5},{"_time":224.0,"_type":13,"_value":5},{"_time":226.0,"_type":0,"_value":3},{"_time":226.0,"_type":1,"_value":3},{"_time":226.0,"_type":4,"_value":3},{"_time":228.0,"_type":2,"_value":2},{"_time":228.0,"_type":3,"_value":2},{"_time":228.0,"_type":8,"_value":0},{"_time":230.0,"_type":1,"_value":3},{"_time":231.0,"_type":1,"_value":3},{"_time":232.0,"_type":0,"_value":3},{"_time":232.0,"_type":1,"_value":3},{"_time":232.0,"_type":4,"_value":2},{"_time":232.0,"_type":8,"_value":0},{"_time":232.0,"_type":12,"_value":5},{"_time":232.0,"_type":13,"_value":5},{"_time":234.0,"_type":1,"_value":3},{"_time":236.0,"_type":0,"_value":3},{"_time":236.0,"_type":8,"_value":0},{"_time":237.0,"_type":1,"_value":3},{"_time":238.0,"_type":1,"_value":3},{"_time":240.0,"_type":1,"_value":3},{"_time":240.0,"_type":4,"_value":2},{"_time":240.0,"_type":8,"_value":0},{"_time":240.0,"_type":12,"_value":6},{"_time":240.0,"_type":13,"_value":6},{"_time":242.0,"_type":0,"_value":3},{"_time":244.0,"_type":1,"_value":3},{"_time":244.0,"_type":8,"_value":0},{"_time":245.0,"_type":0,"_value":3},{"_time":246.0,"_type":1,"_value":3},{"_time":247.0,"_type":1,"_value":3},{"_time":249.0,"_type":0,"_value":3},{"_time":249.0,"_type":1,"_value":3},{"_time":249.0,"_type":2,"_value":2},{"_time":249.0,"_type":3,"_value":2},{"_time":249.0,"_type":4,"_value":2},{"_time":249.0,"_type":12,"_value":7},{"_time":249.0,"_type":13,"_value":7},{"_time":252.0,"_type":0,"_value":3},{"_time":252.0,"_type":8,"_value":0},{"_time":254.0,"_type":1,"_value":3},{"_time":256.0,"_type":0,"_value":3},{"_time":256.0,"_type":4,"_value":2},{"_time":256.0,"_type":8,"_value":0},{"_time":257.0,"_type":1,"_value":3},{"_time":258.0,"_type":0,"_value":3},{"_time":259.0,"_type":1,"_value":3},{"_time":260.0,"_type":0,"_value":3},{"_time":260.0,"_type":1,"_value":0},{"_time":260.0,"_type":2,"_value":0},{"_time":260.0,"_type":3,"_value":0},{"_time":260.0,"_type":4,"_value":3},{"_time":260.0,"_type":8,"_value":0},{"_time":260.0,"_type":12,"_value":0},{"_time":260.0,"_type":13,"_value":0},{"_time":261.0,"_type":2,"_value":3},{"_time":261.0,"_type":3,"_value":3},{"_time":262.0,"_type":0,"_value":7},{"_time":262.0,"_type":4,"_value":7},{"_time":263.0,"_type":1,"_value":7},{"_time":264.0,"_type":0,"_value":2},{"_time":264.0,"_type":1,"_value":3},{"_time":264.0,"_type":2,"_value":2},{"_time":264.0,"_type":3,"_value":2},{"_time":264.0,"_type":4,"_value":3},{"_time":264.0,"_type":8,"_value":0},{"_time":264.0,"_type":9,"_value":0},{"_time":272.0,"_type":0,"_value":7},{"_time":272.0,"_type":1,"_value":6},{"_time":272.0,"_type":2,"_value":0},{"_time":272.0,"_type":3,"_value":0},{"_time":272.0,"_type":4,"_value":6},{"_time":272.0,"_type":8,"_value":0},{"_time":272.0,"_type":9,"_value":1},{"_time":280.0,"_type":0,"_value":2},{"_time":280.0,"_type":1,"_value":3},{"_time":280.0,"_type":2,"_value":2},{"_time":280.0,"_type":3,"_value":2},{"_time":280.0,"_type":4,"_value":3},{"_time":280.0,"_type":8,"_value":0},{"_time":280.0,"_type":9,"_value":0},{"_time":288.0,"_type":0,"_value":6},{"_time":288.0,"_type":1,"_value":6},{"_time":288.0,"_type":2,"_value":0},{"_time":288.0,"_type":3,"_value":0},{"_time":288.0,"_type":4,"_value":0},{"_time":288.0,"_type":8,"_value":0},{"_time":288.0,"_type":9,"_value":1},{"_time":296.0,"_type":0,"_value":7},{"_time":296.0,"_type":1,"_value":7},{"_time":296.0,"_type":2,"_value":7},{"_time":296.0,"_type":3,"_value":7},{"_time":296.0,"_type":4,"_value":6},{"_time":296.0,"_type":8,"_value":0},{"_time":296.0,"_type":9,"_value":0}],"_notes":[{"_time":8.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":14.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":16.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":24.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":30.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":32.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":36.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":40.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":2},{"_time":46.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":48.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":52.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":56.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":62.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":64.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":68.0,"_lineIndex":0,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":72.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":75.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":76.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":79.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":80.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":83.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":84.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":86.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":88.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":91.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":92.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":95.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":96.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":99.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":100.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":102.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":104.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":106.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":108.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":110.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":112.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":114.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":116.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":118.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":120.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":121.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":123.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":124.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":125.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":127.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":128.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":130.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":132.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":133.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":134.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":135.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":136.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":136.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":144.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":144.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":152.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":152.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":160.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":160.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":168.0,"_lineIndex":2,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":168.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":176.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":176.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":184.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":184.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":192.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":192.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":3},{"_time":200.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":202.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":206.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":207.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":208.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":210.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":214.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":215.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":216.0,"_lineIndex":0,"_lineLayer":1,"_type":0,"_cutDirection":2},{"_time":218.0,"_lineIndex":3,"_lineLayer":1,"_type":1,"_cutDirection":3},{"_time":222.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":223.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":224.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":2},{"_time":226.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":230.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":231.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":232.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":234.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":236.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":237.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":238.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":240.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":242.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":244.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":245.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":246.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":247.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":249.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":250.0,"_lineIndex":1,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":252.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":254.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":256.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":257.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":258.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":259.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":260.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":261.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":262.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":263.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":264.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":264.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":272.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":272.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":280.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":280.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1},{"_time":288.0,"_lineIndex":0,"_lineLayer":0,"_type":0,"_cutDirection":0},{"_time":288.0,"_lineIndex":2,"_lineLayer":0,"_type":1,"_cutDirection":0},{"_time":296.0,"_lineIndex":1,"_lineLayer":0,"_type":0,"_cutDirection":1},{"_time":296.0,"_lineIndex":3,"_lineLayer":0,"_type":1,"_cutDirection":1}],"_obstacles":[{"_time":72.0,"_lineIndex":3,"_type":0,"_duration":8.0,"_width":1},{"_time":88.0,"_lineIndex":0,"_type":0,"_duration":8.0,"_width":1},{"_time":168.0,"_lineIndex":0,"_type":0,"_duration":2.0,"_width":1},{"_time":170.0,"_lineIndex":1,"_type":0,"_duration":2.0,"_width":1},{"_time":176.0,"_lineIndex":3,"_type":0,"_duration":2.0,"_width":1},{"_time":178.0,"_lineIndex":2,"_type":0,"_duration":2.0,"_width":1},{"_time":184.0,"_lineIndex":0,"_type":1,"_duration":12.0,"_width":4}]} -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Jaroslav Beck - Beat Saber/cover.png -------------------------------------------------------------------------------- /Research/Jaroslav Beck - Beat Saber/song.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Jaroslav Beck - Beat Saber/song.ogg -------------------------------------------------------------------------------- /Research/Testing map/Easy.dat: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "2.0.0", 3 | "_events": [ 4 | { 5 | "_time": 0, 6 | "_type": 12, 7 | "_value": 6 8 | }, 9 | { 10 | "_time": 1, 11 | "_type": 12, 12 | "_value": 0 13 | }, 14 | { 15 | "_time": 1.5, 16 | "_type": 2, 17 | "_value": 5 18 | }, 19 | { 20 | "_time": 2, 21 | "_type": 2, 22 | "_value": 1 23 | }, 24 | { 25 | "_time": 2.5, 26 | "_type": 2, 27 | "_value": 0 28 | }, 29 | { 30 | "_time": 3, 31 | "_type": 3, 32 | "_value": 5 33 | }, 34 | { 35 | "_time": 3.5, 36 | "_type": 3, 37 | "_value": 1 38 | }, 39 | { 40 | "_time": 4, 41 | "_type": 3, 42 | "_value": 0 43 | }, 44 | { 45 | "_time": 4.5, 46 | "_type": 13, 47 | "_value": 5 48 | }, 49 | { 50 | "_time": 5.5, 51 | "_type": 13, 52 | "_value": 0 53 | }, 54 | { 55 | "_time": 6, 56 | "_type": 0, 57 | "_value": 6 58 | }, 59 | { 60 | "_time": 7, 61 | "_type": 0, 62 | "_value": 7 63 | }, 64 | { 65 | "_time": 7.5, 66 | "_type": 4, 67 | "_value": 2 68 | }, 69 | { 70 | "_time": 8.5, 71 | "_type": 4, 72 | "_value": 3 73 | }, 74 | { 75 | "_time": 9, 76 | "_type": 1, 77 | "_value": 5 78 | }, 79 | { 80 | "_time": 10, 81 | "_type": 1, 82 | "_value": 0 83 | }, 84 | { 85 | "_time": 10.5, 86 | "_type": 8, 87 | "_value": 0 88 | }, 89 | { 90 | "_time": 11.5, 91 | "_type": 8, 92 | "_value": 0 93 | }, 94 | { 95 | "_time": 12, 96 | "_type": 9, 97 | "_value": 0 98 | }, 99 | { 100 | "_time": 13, 101 | "_type": 9, 102 | "_value": 0 103 | } 104 | ], 105 | "_notes": [ 106 | { 107 | "_time": 0, 108 | "_lineIndex": 0, 109 | "_lineLayer": 0, 110 | "_type": 0, 111 | "_cutDirection": 1 112 | }, 113 | { 114 | "_time": 0.5, 115 | "_lineIndex": 0, 116 | "_lineLayer": 0, 117 | "_type": 0, 118 | "_cutDirection": 6 119 | }, 120 | { 121 | "_time": 1, 122 | "_lineIndex": 0, 123 | "_lineLayer": 0, 124 | "_type": 0, 125 | "_cutDirection": 2 126 | }, 127 | { 128 | "_time": 1.5, 129 | "_lineIndex": 0, 130 | "_lineLayer": 0, 131 | "_type": 0, 132 | "_cutDirection": 4 133 | }, 134 | { 135 | "_time": 2, 136 | "_lineIndex": 0, 137 | "_lineLayer": 0, 138 | "_type": 0, 139 | "_cutDirection": 0 140 | }, 141 | { 142 | "_time": 2.5, 143 | "_lineIndex": 0, 144 | "_lineLayer": 0, 145 | "_type": 0, 146 | "_cutDirection": 5 147 | }, 148 | { 149 | "_time": 3, 150 | "_lineIndex": 0, 151 | "_lineLayer": 0, 152 | "_type": 0, 153 | "_cutDirection": 3 154 | }, 155 | { 156 | "_time": 3.5, 157 | "_lineIndex": 0, 158 | "_lineLayer": 0, 159 | "_type": 0, 160 | "_cutDirection": 7 161 | }, 162 | { 163 | "_time": 4, 164 | "_lineIndex": 0, 165 | "_lineLayer": 0, 166 | "_type": 1, 167 | "_cutDirection": 1 168 | }, 169 | { 170 | "_time": 4.5, 171 | "_lineIndex": 0, 172 | "_lineLayer": 0, 173 | "_type": 1, 174 | "_cutDirection": 6 175 | }, 176 | { 177 | "_time": 5, 178 | "_lineIndex": 0, 179 | "_lineLayer": 0, 180 | "_type": 1, 181 | "_cutDirection": 2 182 | }, 183 | { 184 | "_time": 5.5, 185 | "_lineIndex": 0, 186 | "_lineLayer": 0, 187 | "_type": 1, 188 | "_cutDirection": 4 189 | }, 190 | { 191 | "_time": 6, 192 | "_lineIndex": 0, 193 | "_lineLayer": 0, 194 | "_type": 1, 195 | "_cutDirection": 0 196 | }, 197 | { 198 | "_time": 6.5, 199 | "_lineIndex": 0, 200 | "_lineLayer": 0, 201 | "_type": 1, 202 | "_cutDirection": 5 203 | }, 204 | { 205 | "_time": 7, 206 | "_lineIndex": 0, 207 | "_lineLayer": 0, 208 | "_type": 1, 209 | "_cutDirection": 3 210 | }, 211 | { 212 | "_time": 7.5, 213 | "_lineIndex": 0, 214 | "_lineLayer": 0, 215 | "_type": 1, 216 | "_cutDirection": 7 217 | }, 218 | { 219 | "_time": 8, 220 | "_lineIndex": 0, 221 | "_lineLayer": 0, 222 | "_type": 3, 223 | "_cutDirection": 8 224 | }, 225 | { 226 | "_time": 8.5, 227 | "_lineIndex": 1, 228 | "_lineLayer": 0, 229 | "_type": 3, 230 | "_cutDirection": 8 231 | }, 232 | { 233 | "_time": 9, 234 | "_lineIndex": 2, 235 | "_lineLayer": 0, 236 | "_type": 3, 237 | "_cutDirection": 8 238 | }, 239 | { 240 | "_time": 9.5, 241 | "_lineIndex": 3, 242 | "_lineLayer": 0, 243 | "_type": 3, 244 | "_cutDirection": 8 245 | }, 246 | { 247 | "_time": 10, 248 | "_lineIndex": 0, 249 | "_lineLayer": 1, 250 | "_type": 3, 251 | "_cutDirection": 8 252 | }, 253 | { 254 | "_time": 10.5, 255 | "_lineIndex": 1, 256 | "_lineLayer": 1, 257 | "_type": 3, 258 | "_cutDirection": 8 259 | }, 260 | { 261 | "_time": 11, 262 | "_lineIndex": 2, 263 | "_lineLayer": 1, 264 | "_type": 3, 265 | "_cutDirection": 8 266 | }, 267 | { 268 | "_time": 11.5, 269 | "_lineIndex": 3, 270 | "_lineLayer": 1, 271 | "_type": 3, 272 | "_cutDirection": 8 273 | }, 274 | { 275 | "_time": 12, 276 | "_lineIndex": 0, 277 | "_lineLayer": 2, 278 | "_type": 3, 279 | "_cutDirection": 8 280 | }, 281 | { 282 | "_time": 12.5, 283 | "_lineIndex": 1, 284 | "_lineLayer": 2, 285 | "_type": 3, 286 | "_cutDirection": 8 287 | }, 288 | { 289 | "_time": 13, 290 | "_lineIndex": 2, 291 | "_lineLayer": 2, 292 | "_type": 3, 293 | "_cutDirection": 8 294 | }, 295 | { 296 | "_time": 13.5, 297 | "_lineIndex": 3, 298 | "_lineLayer": 2, 299 | "_type": 3, 300 | "_cutDirection": 8 301 | }, 302 | { 303 | "_time": 26, 304 | "_lineIndex": 0, 305 | "_lineLayer": 0, 306 | "_type": 0, 307 | "_cutDirection": 8 308 | }, 309 | { 310 | "_time": 26.5, 311 | "_lineIndex": 0, 312 | "_lineLayer": 0, 313 | "_type": 1, 314 | "_cutDirection": 8 315 | } 316 | ], 317 | "_obstacles": [ 318 | { 319 | "_time": 14, 320 | "_duration": 4, 321 | "_type": 0, 322 | "_lineIndex": 0, 323 | "_width": 1 324 | }, 325 | { 326 | "_time": 18, 327 | "_duration": 4, 328 | "_type": 0, 329 | "_lineIndex": 1, 330 | "_width": 1 331 | }, 332 | { 333 | "_time": 22, 334 | "_duration": 4, 335 | "_type": 0, 336 | "_lineIndex": 2, 337 | "_width": 1 338 | }, 339 | { 340 | "_time": 27.5, 341 | "_duration": 4, 342 | "_type": 1, 343 | "_lineIndex": 0, 344 | "_width": 2 345 | }, 346 | { 347 | "_time": 31.5, 348 | "_duration": 4, 349 | "_type": 1, 350 | "_lineIndex": 2, 351 | "_width": 2 352 | } 353 | ], 354 | "_customData": { 355 | "_bookmarks": [ 356 | 357 | ] 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /Research/Testing map/Screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/Screenshot_1.png -------------------------------------------------------------------------------- /Research/Testing map/Screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/Screenshot_2.png -------------------------------------------------------------------------------- /Research/Testing map/Screenshot_2_.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/Screenshot_2_.png -------------------------------------------------------------------------------- /Research/Testing map/Screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/Screenshot_3.png -------------------------------------------------------------------------------- /Research/Testing map/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/cover.jpg -------------------------------------------------------------------------------- /Research/Testing map/info.dat: -------------------------------------------------------------------------------- 1 | { 2 | "_version": "2.0.0", 3 | "_songName": "Testing", 4 | "_songSubName": "", 5 | "_songAuthorName": "Stijn Rogiest", 6 | "_levelAuthorName": "", 7 | "_beatsPerMinute": 166, 8 | "_songTimeOffset": 0, 9 | "_shuffle": 0, 10 | "_shufflePeriod": 0.5, 11 | "_previewStartTime": 12, 12 | "_previewDuration": 10, 13 | "_songFilename": "song.egg", 14 | "_coverImageFilename": "cover.jpg", 15 | "_environmentName": "DefaultEnvironment", 16 | "_customData": { 17 | "_editor": "beatmapper", 18 | "_editorSettings": { 19 | "modSettings": { 20 | "customColors": { 21 | "isEnabled": false, 22 | "colorLeft": "#f21212", 23 | "colorLeftOverdrive": 0, 24 | "colorRight": "#006cff", 25 | "colorRightOverdrive": 0, 26 | "envColorLeft": "#f21212", 27 | "envColorLeftOverdrive": 0, 28 | "envColorRight": "#006cff", 29 | "envColorRightOverdrive": 0, 30 | "obstacleColor": "#f21212", 31 | "obstacleColorOverdrive": 0 32 | }, 33 | "mappingExtensions": { 34 | "isEnabled": false, 35 | "numRows": 3, 36 | "numCols": 4, 37 | "colWidth": 1, 38 | "rowHeight": 1 39 | } 40 | } 41 | } 42 | }, 43 | "_difficultyBeatmapSets": [ 44 | { 45 | "_beatmapCharacteristicName": "Standard", 46 | "_difficultyBeatmaps": [ 47 | { 48 | "_difficulty": "Easy", 49 | "_difficultyRank": 1, 50 | "_beatmapFilename": "Easy.dat", 51 | "_noteJumpMovementSpeed": 10, 52 | "_noteJumpStartBeatOffset": 0, 53 | "_customData": { 54 | "_editorOffset": 0, 55 | "_requirements": [] 56 | } 57 | } 58 | ] 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /Research/Testing map/song.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/Testing map/song.egg -------------------------------------------------------------------------------- /Research/events.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeStix/Beat-360fyer/ef8aa990ef23a8a8e07f611ec5609332a5a0d1dd/Research/events.xlsx --------------------------------------------------------------------------------