├── .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 | 
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
--------------------------------------------------------------------------------