diff --git a/.gitignore b/.gitignore
index 1ff4432..05d48ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,8 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+# Don't track content of these folders
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
+# Build results #
+#################
[Dd]ebug/
-[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
@@ -24,345 +12,49 @@ bld/
[Oo]bj/
[Ll]og/
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-**/Properties/launchSettings.json
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-# CodeRush
-.cr/
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-[Ll]ibrary/
-[Tt]emp/
-[Oo]bj/
-[Bb]uild/
-[Bb]uilds/
-Assets/AssetStoreTools*
+# User specific files #
+#######################
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
-# Visual Studio cache directory
+# Visual Studio 2015/2017 cache/options directory #
+###################################################
.vs/
-
-# Unity3D generated meta files
-*.pidb.meta
-*.pdb.meta
-
-# Unity3D Generated File On Crash Reports
-sysinfo.txt
-
-# Builds
-*.apk
-*.unitypackage
-
-# Custom
-CustomSaber/*.dll
-
-/CustomSaberEmpty/UnityEngine.CoreModule.dll
-/CustomSaberEmpty/UnityEngine.dll
-/CustomSaberEmpty/UnityEngine.ParticleSystemModule.dll
-/CustomSaberEmpty/UnityEngine.TextRenderingModule.dll
-/CustomSaberEmpty/UnityEngine.UI.dll
-/CustomSaberEmpty/UnityEngine.UIElementsModule.dll
-/CustomSaberEmpty/UnityEngine.UIModule.dll
-/CustomSaberEmpty/UnityEngine.UnityWebRequestWWWModule.dll
-/CustomSaberEmpty/UnityEngine.WebModule.dll
-/CustomSaberEmpty/Mono.WebBrowser.dll
-/CustomSaberEmpty/UnityEngine.AnimationModule.dll
-/CustomSaberEmpty/UnityEngine.AssetBundleModule.dll
-/CustomSaberEmpty/UnityEngine.AudioModule.dll
+# Compiled source #
+###################
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Dynamic Bones source #
+########################
+# We would prefer not to distribute these files, as they are
+# paid assets from the Unity store. Buy them you greedy mushroom!
+*/Dynamic Bones/*.cs
+
+# Unity Project Files #
+#######################
+/UnityProject/Library/*
+/UnityProject/Temp/*
\ No newline at end of file
diff --git a/CustomSaber-Editor/CustomSaber-Editor.csproj b/CustomSaber-Editor/CustomSaber-Editor.csproj
new file mode 100644
index 0000000..01dadd6
--- /dev/null
+++ b/CustomSaber-Editor/CustomSaber-Editor.csproj
@@ -0,0 +1,80 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {272257A9-D168-40E8-985D-A642A6DB60D3}
+ Library
+ Properties
+ CustomSaber_Editor
+ CustomSaber
+ v4.7.2
+ 512
+ $(SolutionDir)=C:\
+ portable
+
+
+ true
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ False
+
+
+
+
+ Data\SaberExtensions\AccuracyReachedEvent.cs
+
+
+ Data\SaberExtensions\EventFilterBehaviour.cs
+
+
+ Data\SaberExtensions\EveryNthComboFilter.cs
+
+
+ Data\SaberExtensions\ComboReachedEvent.cs
+
+
+ Data\SaberExtensions\EventManager.cs
+
+
+ Data\SaberExtensions\SaberDescriptor.cs
+
+
+ Dynamic Bones\DynamicBone.cs
+
+
+ Dynamic Bones\DynamicBoneCollider.cs
+
+
+ Dynamic Bones\DynamicBoneColliderBase.cs
+
+
+ Dynamic Bones\DynamicBonePlaneCollider.cs
+
+
+ Data\SaberExtensions\CustomTrails.cs
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CustomSaber-Editor/Dynamic Bones/DYNAMIC BONE SCRIPTS GOES HERE b/CustomSaber-Editor/Dynamic Bones/DYNAMIC BONE SCRIPTS GOES HERE
new file mode 100644
index 0000000..1440dcf
--- /dev/null
+++ b/CustomSaber-Editor/Dynamic Bones/DYNAMIC BONE SCRIPTS GOES HERE
@@ -0,0 +1 @@
+The 'Dynamic Bone' script is available as a paid asset from the Unity store. We will not provide you with a *free* copy of it, as that just wouldn't feel right.
\ No newline at end of file
diff --git a/CustomSaberEmpty/Properties/AssemblyInfo.cs b/CustomSaber-Editor/Properties/AssemblyInfo.cs
similarity index 73%
rename from CustomSaberEmpty/Properties/AssemblyInfo.cs
rename to CustomSaber-Editor/Properties/AssemblyInfo.cs
index ce5c101..b49ea36 100644
--- a/CustomSaberEmpty/Properties/AssemblyInfo.cs
+++ b/CustomSaber-Editor/Properties/AssemblyInfo.cs
@@ -2,35 +2,35 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("Katana")]
+[assembly: AssemblyTitle("CustomSaber-Editor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Katana")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyProduct("CustomSaber-Editor")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("fef74b0a-6772-4659-a782-334f1491d103")]
+[assembly: Guid("272257a9-d168-40e8-985d-a642a6db60d3")]
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("4.3.0")]
+[assembly: AssemblyFileVersion("4.3.0")]
diff --git a/CustomSaber/CustomSaber.sln b/CustomSaber.sln
similarity index 52%
rename from CustomSaber/CustomSaber.sln
rename to CustomSaber.sln
index 7b25703..b67847c 100644
--- a/CustomSaber/CustomSaber.sln
+++ b/CustomSaber.sln
@@ -1,9 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2000
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29613.14
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSaber", "CustomSaber.csproj", "{FEF74B0A-6772-4659-A782-334F1491D103}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSaber", "CustomSaber\CustomSaber.csproj", "{FEF74B0A-6772-4659-A782-334F1491D103}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSaber-Editor", "CustomSaber-Editor\CustomSaber-Editor.csproj", "{272257A9-D168-40E8-985D-A642A6DB60D3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{81F59A18-EDEE-49B4-AF5D-12E7CA17ECD2}"
+ ProjectSection(SolutionItems) = preProject
+ .gitignore = .gitignore
+ README.md = README.md
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +23,10 @@ Global
{FEF74B0A-6772-4659-A782-334F1491D103}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FEF74B0A-6772-4659-A782-334F1491D103}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FEF74B0A-6772-4659-A782-334F1491D103}.Release|Any CPU.Build.0 = Release|Any CPU
+ {272257A9-D168-40E8-985D-A642A6DB60D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {272257A9-D168-40E8-985D-A642A6DB60D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {272257A9-D168-40E8-985D-A642A6DB60D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {272257A9-D168-40E8-985D-A642A6DB60D3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/CustomSaber/CustomSaber.csproj b/CustomSaber/CustomSaber.csproj
index f79b0ba..9a854fa 100644
--- a/CustomSaber/CustomSaber.csproj
+++ b/CustomSaber/CustomSaber.csproj
@@ -9,16 +9,15 @@
Properties
CustomSaber
CustomSaber
- v4.6.1
+ v4.7.2
512
-
true
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG;PLUGIN
prompt
4
false
@@ -27,123 +26,132 @@
pdbonly
true
bin\Release\
- TRACE
+ TRACE;PLUGIN
prompt
4
false
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\0Harmony.dll
-
-
- False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp.dll
-
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp-firstpass.dll
-
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Plugins\BeatSaberCustomUI.dll
+
+ $(BeatSaberDir)\Plugins\BSML.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Plugins\CustomColors.dll
+
+ $(BeatSaberDir)\Plugins\BS_Utils.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IllusionInjector.dll
+
+ Z:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Colors.dll
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IllusionPlugin.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\HMLib.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Mono.Data.Sqlite.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\HMUI.dll
+ False
-
- False
- ..\..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Mono.Posix.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Mono.Security.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Mono.WebBrowser.dll
+
+ $(BeatSaberDir)\Libs\SemVer.dll
+ False
-
-
-
-
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\TextMeshPro-1.0.55.2017.1.0b12.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
+ False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.dll
-
-
- False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AnimationModule.dll
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll
+ False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AssetBundleModule.dll
-
-
- False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AudioModule.dll
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.AssetBundleModule.dll
+ False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.IMGUIModule.dll
-
-
- False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.ParticleSystemModule.dll
-
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.TextRenderingModule.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.ImageConversionModule.dll
+ False
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UI.dll
-
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll
+ False
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIModule.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.XRModule.dll
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll
+
+ $(BeatSaberDir)\Beat Saber\Beat Saber_Data\Managed\VRUI.dll
-
- C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.WebModule.dll
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject.dll
+ False
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- copy /Y "$(TargetDir)$(TargetFileName)" "C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Plugins"
+ copy "$(TargetPath)" "$(BeatSaberDir)\Plugins"
\ No newline at end of file
diff --git a/CustomSaber/CustomTrails.cs b/CustomSaber/CustomTrails.cs
deleted file mode 100644
index c118316..0000000
--- a/CustomSaber/CustomTrails.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using UnityEngine;
-using Xft;
-
-namespace CustomSaber
-{
- public enum ColorType
- {
- LeftSaber,
- RightSaber,
- CustomColor
- }
-
- public class CustomTrail : MonoBehaviour
- {
-
- public Transform PointStart;
- public Transform PointEnd;
- public Material TrailMaterial;
- public ColorType colorType = ColorType.CustomColor;
- public Color TrailColor = new Color(1.0f,1.0f,1.0f,1.0f);
- public Color MultiplierColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
- public int Length = 20;
-
- private CustomWeaponTrail trail;
- private ColorManager oldColorManager;
- private XWeaponTrailRenderer oldTrailRendererPrefab;
- private Saber saber;
-
- public void Init(Saber parentSaber)
- {
- Console.WriteLine("Replacing Trail");
-
- saber = parentSaber;
-
- if (gameObject.name != "LeftSaber" && gameObject.name != "RightSaber")
- {
- Console.WriteLine("Parent not LeftSaber or RightSaber");
- Destroy(this);
- }
-
- if (saber == null)
- {
- Console.WriteLine("Saber not found");
- Destroy(this);
- }
-
- SaberWeaponTrail oldtrail = saber.GetComponent();
- if (oldtrail != null)
- {
- try
- {
- ReflectionUtil.SetPrivateField(oldtrail, "_multiplierSaberColor", new Color(0f, 0f, 0f, 0f));
- oldColorManager = ReflectionUtil.GetPrivateField(oldtrail, "_colorManager");
- oldTrailRendererPrefab = ReflectionUtil.GetPrivateField(oldtrail, "_trailRendererPrefab");
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- Console.WriteLine(e.Message);
- throw;
- }
-
- trail = gameObject.AddComponent();
- trail.init(oldTrailRendererPrefab, oldColorManager, PointStart, PointEnd, TrailMaterial, TrailColor, Length, MultiplierColor, colorType);
- }
- else
- {
- Console.WriteLine("Trail not found");
- Destroy(this);
- }
- }
-
- public void EnableTrail(bool enable)
- {
- trail.enabled = enable;
- }
-
- public void SetMaterial(Material newMat)
- {
- TrailMaterial = newMat;
- trail.SetMaterial(newMat);
- }
-
- public void SetColor(Color newColor)
- {
- TrailColor = newColor;
- trail.SetColor(newColor);
- }
- }
-}
diff --git a/CustomSaber/CustomWeaponTrail.cs b/CustomSaber/CustomWeaponTrail.cs
deleted file mode 100644
index 7393296..0000000
--- a/CustomSaber/CustomWeaponTrail.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using System;
-using UnityEngine;
-using Xft;
-
-
-namespace CustomSaber
-{
- class CustomWeaponTrail : XWeaponTrail
- {
- public ColorType _saberType;
- public ColorManager _colorManager;
- public Color _multiplierSaberColor;
- public Color _customColor;
- public Material _customMaterial;
-
- protected override Color color
- {
- get
- {
- if (_saberType.Equals(ColorType.LeftSaber) && _colorManager != null)
- {
- return _colorManager.ColorForSaberType(Saber.SaberType.SaberA) * _multiplierSaberColor;
- }
- else if (_saberType.Equals(ColorType.RightSaber) && _colorManager != null)
- {
- return _colorManager.ColorForSaberType(Saber.SaberType.SaberB) * _multiplierSaberColor;
- }
- else
- {
- return _customColor * _multiplierSaberColor;
- }
- }
- }
-
- public void init(XWeaponTrailRenderer TrailRendererPrefab, ColorManager colorManager, Transform PointStart, Transform PointEnd, Material TrailMaterial, Color TrailColor, int Length, Color multiplierSaberColor, ColorType colorType)
- {
- _pointStart = PointStart;
- _pointEnd = PointEnd;
- _maxFrame = Length;
- _colorManager = colorManager;
- _trailRendererPrefab = TrailRendererPrefab;
- _multiplierSaberColor = multiplierSaberColor;
- _customColor = TrailColor;
- _customMaterial = TrailMaterial;
- _saberType = colorType;
- }
-
- public override void Start()
- {
- base.Start();
-
- ReflectionUtil.GetPrivateField(_trailRenderer, "_meshRenderer").material = _customMaterial;
- }
-
- public void SetColor(Color newColor)
- {
- _customColor = newColor;
- }
-
- public void SetMaterial(Material newMaterial)
- {
- _customMaterial = newMaterial;
- ReflectionUtil.GetPrivateField(_trailRenderer, "_meshRenderer").material = _customMaterial;
- }
- }
-}
diff --git a/CustomSaber/Data/CustomSaberData.cs b/CustomSaber/Data/CustomSaberData.cs
new file mode 100644
index 0000000..03d7b88
--- /dev/null
+++ b/CustomSaber/Data/CustomSaberData.cs
@@ -0,0 +1,94 @@
+using CustomSaber.Utilities;
+using System.IO;
+using UnityEngine;
+
+namespace CustomSaber.Data
+{
+ public class CustomSaberData
+ {
+ public string FileName { get; }
+ public AssetBundle AssetBundle { get; }
+ public SaberDescriptor Descriptor { get; }
+ public GameObject Sabers { get; }
+ public string ErrorMessage { get; } = string.Empty;
+
+ public CustomSaberData(string fileName)
+ {
+ FileName = fileName;
+
+ if (fileName != "DefaultSabers")
+ {
+ try
+ {
+ AssetBundle = AssetBundle.LoadFromFile(Path.Combine(Plugin.PluginAssetPath, fileName));
+ Sabers = AssetBundle.LoadAsset("_CustomSaber");
+ Descriptor = Sabers.GetComponent();
+ Descriptor.CoverImage = Descriptor.CoverImage ?? Utils.GetDefaultCoverImage();
+ }
+ catch
+ {
+ Logger.log.Warn($"Something went wrong getting the AssetBundle for '{fileName}'!");
+
+ Descriptor = new SaberDescriptor
+ {
+ SaberName = "Invalid Saber (Delete it)",
+ AuthorName = fileName,
+ CoverImage = Utils.GetErrorCoverImage()
+ };
+
+ ErrorMessage = $"File: '{fileName}'" +
+ "\n\nThis file failed to load." +
+ "\n\nThis may have been caused by having duplicated files," +
+ " another saber with the same name already exists or that the custom saber is simply just broken." +
+ "\n\nThe best thing is probably just to delete it!";
+
+ FileName = "DefaultSabers";
+ }
+ }
+ else
+ {
+ Descriptor = new SaberDescriptor
+ {
+ SaberName = "Default",
+ AuthorName = "Beat Saber",
+ Description = "This is the default sabers. (No preview available)",
+ CoverImage = Utils.GetRandomCoverImage(),
+ };
+ }
+ }
+
+ public CustomSaberData(GameObject leftSaber, GameObject rightSaber)
+ {
+ FileName = "DefaultSabers";
+
+ Descriptor = new SaberDescriptor
+ {
+ SaberName = "Default",
+ AuthorName = "Beat Games",
+ Description = "This is the default sabers.",
+ CoverImage = Utils.GetRandomCoverImage(),
+ };
+
+ GameObject saberParent = new GameObject();
+ if (saberParent)
+ {
+ leftSaber.transform.SetParent(saberParent.transform);
+ rightSaber.transform.SetParent(saberParent.transform);
+ }
+
+ Sabers = saberParent;
+ }
+
+ public void Destroy()
+ {
+ if (AssetBundle != null)
+ {
+ AssetBundle.Unload(true);
+ }
+ else
+ {
+ Object.Destroy(Descriptor);
+ }
+ }
+ }
+}
diff --git a/CustomSaber/Data/SaberExtensions/AccuracyReachedEvent.cs b/CustomSaber/Data/SaberExtensions/AccuracyReachedEvent.cs
new file mode 100644
index 0000000..f782ea2
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/AccuracyReachedEvent.cs
@@ -0,0 +1,46 @@
+using UnityEngine.Events;
+
+// Class has to be in this namespace due to compatibility
+namespace CustomSaber
+{
+ [UnityEngine.AddComponentMenu("Custom Sabers/Accuracy Reached Event")]
+ public class AccuracyReachedEvent : EventFilterBehaviour
+ {
+ [UnityEngine.Tooltip("Event will be triggered when accuracy crosses this value, expressed as a value between 0 and 1")]
+ [UnityEngine.RangeAttribute(0f, 1f)]
+ public float Target = 1.0f;
+ public UnityEvent OnAccuracyReachTarget;
+ public UnityEvent OnAccuracyHigherThanTarget;
+ public UnityEvent OnAccuracyLowerThanTarget;
+
+#if PLUGIN
+ private void OnEnable()
+ {
+ EventManager.OnAccuracyChanged.AddListener(OnAccuracyReached);
+ prevAccuracy = 1.0f;
+ }
+
+ private void OnDisable() => EventManager.OnAccuracyChanged.RemoveListener(OnAccuracyReached);
+
+ private float prevAccuracy;
+
+ private void OnAccuracyReached(float accuracy)
+ {
+ if (prevAccuracy > Target && accuracy < Target || prevAccuracy < Target && accuracy > Target)
+ {
+ OnAccuracyReachTarget.Invoke();
+ }
+ if (prevAccuracy < Target && accuracy > Target)
+ {
+ OnAccuracyHigherThanTarget.Invoke();
+ }
+ if (prevAccuracy > Target && accuracy < Target)
+ {
+ OnAccuracyLowerThanTarget.Invoke();
+ }
+
+ prevAccuracy = accuracy;
+ }
+#endif
+ }
+}
diff --git a/CustomSaber/Data/SaberExtensions/ComboReachedEvent.cs b/CustomSaber/Data/SaberExtensions/ComboReachedEvent.cs
new file mode 100644
index 0000000..76ee8bc
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/ComboReachedEvent.cs
@@ -0,0 +1,25 @@
+using UnityEngine.Events;
+
+// Class has to be in this namespace due to compatibility
+namespace CustomSaber
+{
+ [UnityEngine.AddComponentMenu("Custom Sabers/Combo Reached Event")]
+ public class ComboReachedEvent : EventFilterBehaviour
+ {
+ public int ComboTarget = 50;
+ public UnityEvent NthComboReached;
+
+#if PLUGIN
+ private void OnEnable() => EventManager.OnComboChanged.AddListener(OnComboReached);
+ private void OnDisable() => EventManager.OnComboChanged.RemoveListener(OnComboReached);
+
+ private void OnComboReached(int combo)
+ {
+ if (combo == ComboTarget)
+ {
+ NthComboReached.Invoke();
+ }
+ }
+#endif
+ }
+}
diff --git a/CustomSaber/Data/SaberExtensions/CustomTrails.cs b/CustomSaber/Data/SaberExtensions/CustomTrails.cs
new file mode 100644
index 0000000..fce0b3e
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/CustomTrails.cs
@@ -0,0 +1,121 @@
+#if PLUGIN
+using CustomSaber.Settings;
+using CustomSaber.Utilities;
+using IPA.Utilities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xft;
+#endif
+using UnityEngine;
+
+// Class has to be in this namespace due to compatibility
+namespace CustomSaber
+{
+ public enum ColorType
+ {
+ LeftSaber,
+ RightSaber,
+ CustomColor
+ }
+
+ [UnityEngine.AddComponentMenu("Custom Sabers/Custom Trail")]
+ public class CustomTrail : MonoBehaviour
+ {
+ public Transform PointStart;
+ public Transform PointEnd;
+ public Material TrailMaterial;
+ public ColorType colorType = ColorType.CustomColor;
+ public Color TrailColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
+ public Color MultiplierColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
+ public int Length = 20;
+ public int Granularity = 60;
+
+#if PLUGIN
+ private CustomWeaponTrail trail;
+ private XWeaponTrailRenderer oldTrailRendererPrefab;
+
+ public void Init(Saber saber, ColorManager colorManager)
+ {
+ Logger.log.Debug($"Replacing Trail for '{saber?.saberType}'");
+
+ if (gameObject.name != "LeftSaber" && gameObject.name != "RightSaber")
+ {
+ Logger.log.Warn("Parent not LeftSaber or RightSaber");
+ Destroy(this);
+ }
+
+ if (!saber)
+ {
+ Logger.log.Warn("Saber not found");
+ Destroy(this);
+ }
+
+ IEnumerable trails = Resources.FindObjectsOfTypeAll();
+ foreach (XWeaponTrail trail in trails)
+ {
+ ReflectionUtil.SetField(trail, "_trailWidth", 0f);
+ }
+
+ XWeaponTrail oldtrail = Resources.FindObjectsOfTypeAll().FirstOrDefault()
+ ?.GetField("_basicSaberModelControllerPrefab")
+ ?.GetField("_saberWeaponTrail");
+
+ if (oldtrail)
+ {
+ try
+ {
+ oldTrailRendererPrefab = ReflectionUtil.GetField(oldtrail, "_trailRendererPrefab");
+ }
+ catch (Exception ex)
+ {
+ Logger.log.Error(ex);
+ throw;
+ }
+
+ if (Configuration.OverrideTrailLength)
+ {
+ Length = (int)(Length * Configuration.TrailLength);
+ Granularity = (int)(Granularity * Configuration.TrailLength);
+ }
+
+ if (Length > 1)
+ {
+ trail = gameObject.AddComponent();
+ trail.Init(oldTrailRendererPrefab, colorManager, PointStart, PointEnd, TrailMaterial, TrailColor, Length, Granularity, MultiplierColor, colorType);
+ }
+
+ //if (Configuration.OverrideTrailLength) SetGranularity((int)(trail.GetField("_granularity") * Configuration.TrailLength));
+ }
+ else
+ {
+ Logger.log.Debug($"Trail not found for '{saber?.saberType}'");
+ Destroy(this);
+ }
+ }
+
+ public void EnableTrail(bool enable)
+ {
+ trail.enabled = enable;
+ }
+
+ public void SetMaterial(Material newMat)
+ {
+ TrailMaterial = newMat;
+ trail.SetMaterial(newMat);
+ }
+
+ public void SetColor(Color newColor)
+ {
+ TrailColor = newColor;
+ trail.SetColor(newColor);
+ }
+
+ public void SetGranularity(int granularity)
+ {
+ ReflectionUtil.SetProperty(trail, "_granularity", granularity);
+ Logger.log.Info($"granularity: {trail.GetField("_granularity").ToString()}");
+ }
+#endif
+ }
+}
diff --git a/CustomSaber/Data/SaberExtensions/EventFilterBehaviour.cs b/CustomSaber/Data/SaberExtensions/EventFilterBehaviour.cs
new file mode 100644
index 0000000..673027d
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/EventFilterBehaviour.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+// Class has to be in this namespace due to compatibility
+namespace CustomSaber
+{
+ [RequireComponent(typeof(EventManager))]
+ public class EventFilterBehaviour : MonoBehaviour
+ {
+ private EventManager eventManager;
+ protected EventManager EventManager
+ {
+ get
+ {
+ if (eventManager == null)
+ {
+ eventManager = GetComponent();
+ }
+
+ return eventManager;
+ }
+ }
+ }
+}
diff --git a/CustomSaberEmpty/EventManager.cs b/CustomSaber/Data/SaberExtensions/EventManager.cs
similarity index 62%
rename from CustomSaberEmpty/EventManager.cs
rename to CustomSaber/Data/SaberExtensions/EventManager.cs
index 341d191..c895235 100644
--- a/CustomSaberEmpty/EventManager.cs
+++ b/CustomSaber/Data/SaberExtensions/EventManager.cs
@@ -2,11 +2,12 @@
using UnityEngine;
using UnityEngine.Events;
+// Class has to be in this namespace due to compatibility
namespace CustomSaber
{
+ [AddComponentMenu("Custom Sabers/Event Manager")]
public class EventManager : MonoBehaviour
{
-
public UnityEvent OnSlice;
public UnityEvent OnComboBreak;
public UnityEvent MultiplierUp;
@@ -18,11 +19,15 @@ public class EventManager : MonoBehaviour
public UnityEvent OnBlueLightOn;
public UnityEvent OnRedLightOn;
+ [HideInInspector]
+ public ComboChangedEvent OnComboChanged = new ComboChangedEvent();
+ [HideInInspector]
+ public AccuracyChangedEvent OnAccuracyChanged = new AccuracyChangedEvent();
+
[Serializable]
- public class ComboChangedEvent : UnityEvent
- {
- }
+ public class ComboChangedEvent : UnityEvent { }
- public ComboChangedEvent OnComboChanged = new ComboChangedEvent();
+ [Serializable]
+ public class AccuracyChangedEvent : UnityEvent { }
}
-}
\ No newline at end of file
+}
diff --git a/CustomSaber/Data/SaberExtensions/EveryNthComboFilter.cs b/CustomSaber/Data/SaberExtensions/EveryNthComboFilter.cs
new file mode 100644
index 0000000..b1b9593
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/EveryNthComboFilter.cs
@@ -0,0 +1,25 @@
+using UnityEngine.Events;
+
+// Class has to be in this namespace due to compatibility
+namespace CustomSaber
+{
+ [UnityEngine.AddComponentMenu("Custom Sabers/Every Nth Combo")]
+ public class EveryNthComboFilter : EventFilterBehaviour
+ {
+ public int ComboStep = 50;
+ public UnityEvent NthComboReached;
+
+#if PLUGIN
+ private void OnEnable() => EventManager.OnComboChanged.AddListener(OnComboStep);
+ private void OnDisable() => EventManager.OnComboChanged.RemoveListener(OnComboStep);
+
+ private void OnComboStep(int combo)
+ {
+ if (combo % ComboStep == 0 && combo != 0)
+ {
+ NthComboReached.Invoke();
+ }
+ }
+#endif
+ }
+}
diff --git a/CustomSaber/Data/SaberExtensions/SaberDescriptor.cs b/CustomSaber/Data/SaberExtensions/SaberDescriptor.cs
new file mode 100644
index 0000000..c73b47c
--- /dev/null
+++ b/CustomSaber/Data/SaberExtensions/SaberDescriptor.cs
@@ -0,0 +1,11 @@
+using UnityEngine;
+
+// Class has to be in this namespace due to compatibility
+[AddComponentMenu("Custom Sabers/Saber Descriptor")]
+public class SaberDescriptor : MonoBehaviour
+{
+ public string SaberName = "saber";
+ public string AuthorName = "author";
+ public string Description = string.Empty;
+ public Sprite CoverImage = null;
+}
diff --git a/CustomSaber/DynamicBone.cs b/CustomSaber/DynamicBone.cs
deleted file mode 100644
index 784a08d..0000000
--- a/CustomSaber/DynamicBone.cs
+++ /dev/null
@@ -1,739 +0,0 @@
-using System;
-using System.Collections.Generic;
-using UnityEngine;
-
-// Token: 0x02000003 RID: 3
-[AddComponentMenu("Dynamic Bone/Dynamic Bone")]
-public class DynamicBone : MonoBehaviour
-{
- // Token: 0x06000002 RID: 2 RVA: 0x0000206F File Offset: 0x0000026F
- private void Start()
- {
- this.SetupParticles();
- }
-
- // Token: 0x06000003 RID: 3 RVA: 0x0000207C File Offset: 0x0000027C
- private void Update()
- {
- bool flag = this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled);
- if (flag)
- {
- this.InitTransforms();
- }
- }
-
- // Token: 0x06000004 RID: 4 RVA: 0x000020BC File Offset: 0x000002BC
- private void LateUpdate()
- {
- bool distantDisable = this.m_DistantDisable;
- if (distantDisable)
- {
- this.CheckDistance();
- }
- bool flag = this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled);
- if (flag)
- {
- this.UpdateDynamicBones(Time.deltaTime);
- }
- }
-
- // Token: 0x06000005 RID: 5 RVA: 0x00002110 File Offset: 0x00000310
- private void CheckDistance()
- {
- Transform transform = this.m_ReferenceObject;
- bool flag = transform == null && Camera.main != null;
- if (flag)
- {
- transform = Camera.main.transform;
- }
- bool flag2 = transform != null;
- if (flag2)
- {
- float sqrMagnitude = (transform.position - base.transform.position).sqrMagnitude;
- bool flag3 = sqrMagnitude > this.m_DistanceToObject * this.m_DistanceToObject;
- bool flag4 = flag3 != this.m_DistantDisabled;
- if (flag4)
- {
- bool flag5 = !flag3;
- if (flag5)
- {
- this.ResetParticlesPosition();
- }
- this.m_DistantDisabled = flag3;
- }
- }
- }
-
- // Token: 0x06000006 RID: 6 RVA: 0x000021B9 File Offset: 0x000003B9
- private void OnEnable()
- {
- this.ResetParticlesPosition();
- }
-
- // Token: 0x06000007 RID: 7 RVA: 0x000021C3 File Offset: 0x000003C3
- private void OnDisable()
- {
- this.InitTransforms();
- }
-
- // Token: 0x06000008 RID: 8 RVA: 0x000021D0 File Offset: 0x000003D0
- private void OnValidate()
- {
- this.m_UpdateRate = Mathf.Max(this.m_UpdateRate, 0f);
- this.m_Damping = Mathf.Clamp01(this.m_Damping);
- this.m_Elasticity = Mathf.Clamp01(this.m_Elasticity);
- this.m_Stiffness = Mathf.Clamp01(this.m_Stiffness);
- this.m_Inert = Mathf.Clamp01(this.m_Inert);
- this.m_Radius = Mathf.Max(this.m_Radius, 0f);
- bool flag = Application.isEditor && Application.isPlaying;
- if (flag)
- {
- this.InitTransforms();
- this.SetupParticles();
- }
- }
-
- // Token: 0x06000009 RID: 9 RVA: 0x00002274 File Offset: 0x00000474
- private void OnDrawGizmosSelected()
- {
- bool flag = !base.enabled || this.m_Root == null;
- if (!flag)
- {
- bool flag2 = Application.isEditor && !Application.isPlaying && base.transform.hasChanged;
- if (flag2)
- {
- this.InitTransforms();
- this.SetupParticles();
- }
- Gizmos.color = Color.white;
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- bool flag3 = particle.m_ParentIndex >= 0;
- if (flag3)
- {
- DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
- Gizmos.DrawLine(particle.m_Position, particle2.m_Position);
- }
- bool flag4 = particle.m_Radius > 0f;
- if (flag4)
- {
- Gizmos.DrawWireSphere(particle.m_Position, particle.m_Radius * this.m_ObjectScale);
- }
- }
- }
- }
-
- // Token: 0x0600000A RID: 10 RVA: 0x00002374 File Offset: 0x00000574
- public void SetWeight(float w)
- {
- bool flag = this.m_Weight != w;
- if (flag)
- {
- bool flag2 = w == 0f;
- if (flag2)
- {
- this.InitTransforms();
- }
- else
- {
- bool flag3 = this.m_Weight == 0f;
- if (flag3)
- {
- this.ResetParticlesPosition();
- }
- }
- this.m_Weight = w;
- }
- }
-
- // Token: 0x0600000B RID: 11 RVA: 0x000023C8 File Offset: 0x000005C8
- public float GetWeight()
- {
- return this.m_Weight;
- }
-
- // Token: 0x0600000C RID: 12 RVA: 0x000023E0 File Offset: 0x000005E0
- private void UpdateDynamicBones(float t)
- {
- bool flag = this.m_Root == null;
- if (!flag)
- {
- this.m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x);
- this.m_ObjectMove = base.transform.position - this.m_ObjectPrevPosition;
- this.m_ObjectPrevPosition = base.transform.position;
- int num = 1;
- bool flag2 = this.m_UpdateRate > 0f;
- if (flag2)
- {
- float num2 = 1f / this.m_UpdateRate;
- this.m_Time += t;
- num = 0;
- while (this.m_Time >= num2)
- {
- this.m_Time -= num2;
- bool flag3 = ++num >= 3;
- if (flag3)
- {
- this.m_Time = 0f;
- break;
- }
- }
- }
- bool flag4 = num > 0;
- if (flag4)
- {
- for (int i = 0; i < num; i++)
- {
- this.UpdateParticles1();
- this.UpdateParticles2();
- this.m_ObjectMove = Vector3.zero;
- }
- }
- else
- {
- this.SkipUpdateParticles();
- }
- this.ApplyParticlesToTransforms();
- }
- }
-
- // Token: 0x0600000D RID: 13 RVA: 0x00002510 File Offset: 0x00000710
- private void SetupParticles()
- {
- this.m_Particles.Clear();
- bool flag = this.m_Root == null;
- if (!flag)
- {
- this.m_LocalGravity = this.m_Root.InverseTransformDirection(this.m_Gravity);
- this.m_ObjectScale = base.transform.lossyScale.x;
- this.m_ObjectPrevPosition = base.transform.position;
- this.m_ObjectMove = Vector3.zero;
- this.m_BoneTotalLength = 0f;
- this.AppendParticles(this.m_Root, -1, 0f);
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- particle.m_Damping = this.m_Damping;
- particle.m_Elasticity = this.m_Elasticity;
- particle.m_Stiffness = this.m_Stiffness;
- particle.m_Inert = this.m_Inert;
- particle.m_Radius = this.m_Radius;
- bool flag2 = this.m_BoneTotalLength > 0f;
- if (flag2)
- {
- float num = particle.m_BoneLength / this.m_BoneTotalLength;
- bool flag3 = this.m_DampingDistrib != null && this.m_DampingDistrib.keys.Length != 0;
- if (flag3)
- {
- particle.m_Damping *= this.m_DampingDistrib.Evaluate(num);
- }
- bool flag4 = this.m_ElasticityDistrib != null && this.m_ElasticityDistrib.keys.Length != 0;
- if (flag4)
- {
- particle.m_Elasticity *= this.m_ElasticityDistrib.Evaluate(num);
- }
- bool flag5 = this.m_StiffnessDistrib != null && this.m_StiffnessDistrib.keys.Length != 0;
- if (flag5)
- {
- particle.m_Stiffness *= this.m_StiffnessDistrib.Evaluate(num);
- }
- bool flag6 = this.m_InertDistrib != null && this.m_InertDistrib.keys.Length != 0;
- if (flag6)
- {
- particle.m_Inert *= this.m_InertDistrib.Evaluate(num);
- }
- bool flag7 = this.m_RadiusDistrib != null && this.m_RadiusDistrib.keys.Length != 0;
- if (flag7)
- {
- particle.m_Radius *= this.m_RadiusDistrib.Evaluate(num);
- }
- }
- particle.m_Damping = Mathf.Clamp01(particle.m_Damping);
- particle.m_Elasticity = Mathf.Clamp01(particle.m_Elasticity);
- particle.m_Stiffness = Mathf.Clamp01(particle.m_Stiffness);
- particle.m_Inert = Mathf.Clamp01(particle.m_Inert);
- particle.m_Radius = Mathf.Max(particle.m_Radius, 0f);
- }
- }
- }
-
- // Token: 0x0600000E RID: 14 RVA: 0x000027B4 File Offset: 0x000009B4
- private void AppendParticles(Transform b, int parentIndex, float boneLength)
- {
- DynamicBone.Particle particle = new DynamicBone.Particle();
- particle.m_Transform = b;
- particle.m_ParentIndex = parentIndex;
- bool flag = b != null;
- if (flag)
- {
- particle.m_Position = (particle.m_PrevPosition = b.position);
- particle.m_InitLocalPosition = b.localPosition;
- particle.m_InitLocalRotation = b.localRotation;
- }
- else
- {
- Transform transform = this.m_Particles[parentIndex].m_Transform;
- bool flag2 = this.m_EndLength > 0f;
- if (flag2)
- {
- Transform parent = transform.parent;
- bool flag3 = parent != null;
- if (flag3)
- {
- particle.m_EndOffset = transform.InverseTransformPoint(transform.position * 2f - parent.position) * this.m_EndLength;
- }
- else
- {
- particle.m_EndOffset = new Vector3(this.m_EndLength, 0f, 0f);
- }
- }
- else
- {
- particle.m_EndOffset = transform.InverseTransformPoint(base.transform.TransformDirection(this.m_EndOffset) + transform.position);
- }
- particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
- }
- bool flag4 = parentIndex >= 0;
- if (flag4)
- {
- boneLength += (this.m_Particles[parentIndex].m_Transform.position - particle.m_Position).magnitude;
- particle.m_BoneLength = boneLength;
- this.m_BoneTotalLength = Mathf.Max(this.m_BoneTotalLength, boneLength);
- }
- int count = this.m_Particles.Count;
- this.m_Particles.Add(particle);
- bool flag5 = b != null;
- if (flag5)
- {
- for (int i = 0; i < b.childCount; i++)
- {
- bool flag6 = false;
- bool flag7 = this.m_Exclusions != null;
- if (flag7)
- {
- for (int j = 0; j < this.m_Exclusions.Count; j++)
- {
- Transform transform2 = this.m_Exclusions[j];
- bool flag8 = transform2 == b.GetChild(i);
- if (flag8)
- {
- flag6 = true;
- break;
- }
- }
- }
- bool flag9 = !flag6;
- if (flag9)
- {
- this.AppendParticles(b.GetChild(i), count, boneLength);
- }
- }
- bool flag10 = b.childCount == 0 && (this.m_EndLength > 0f || this.m_EndOffset != Vector3.zero);
- if (flag10)
- {
- this.AppendParticles(null, count, boneLength);
- }
- }
- }
-
- // Token: 0x0600000F RID: 15 RVA: 0x00002A4C File Offset: 0x00000C4C
- private void InitTransforms()
- {
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- bool flag = particle.m_Transform != null;
- if (flag)
- {
- particle.m_Transform.localPosition = particle.m_InitLocalPosition;
- particle.m_Transform.localRotation = particle.m_InitLocalRotation;
- }
- }
- }
-
- // Token: 0x06000010 RID: 16 RVA: 0x00002ABC File Offset: 0x00000CBC
- private void ResetParticlesPosition()
- {
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- bool flag = particle.m_Transform != null;
- if (flag)
- {
- particle.m_Position = (particle.m_PrevPosition = particle.m_Transform.position);
- }
- else
- {
- Transform transform = this.m_Particles[particle.m_ParentIndex].m_Transform;
- particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
- }
- }
- this.m_ObjectPrevPosition = base.transform.position;
- }
-
- // Token: 0x06000011 RID: 17 RVA: 0x00002B70 File Offset: 0x00000D70
- private void UpdateParticles1()
- {
- Vector3 vector = this.m_Gravity;
- Vector3 normalized = this.m_Gravity.normalized;
- Vector3 vector2 = this.m_Root.TransformDirection(this.m_LocalGravity);
- Vector3 vector3 = normalized * Mathf.Max(Vector3.Dot(vector2, normalized), 0f);
- vector -= vector3;
- vector = (vector + this.m_Force) * this.m_ObjectScale;
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- bool flag = particle.m_ParentIndex >= 0;
- if (flag)
- {
- Vector3 vector4 = particle.m_Position - particle.m_PrevPosition;
- Vector3 vector5 = this.m_ObjectMove * particle.m_Inert;
- particle.m_PrevPosition = particle.m_Position + vector5;
- particle.m_Position += vector4 * (1f - particle.m_Damping) + vector + vector5;
- }
- else
- {
- particle.m_PrevPosition = particle.m_Position;
- particle.m_Position = particle.m_Transform.position;
- }
- }
- }
-
- // Token: 0x06000012 RID: 18 RVA: 0x00002CC0 File Offset: 0x00000EC0
- private void UpdateParticles2()
- {
- Plane plane = default(Plane);
- for (int i = 1; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
- bool flag = particle.m_Transform != null;
- float magnitude;
- if (flag)
- {
- magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude;
- }
- else
- {
- magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude;
- }
- float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight);
- bool flag2 = num > 0f || particle.m_Elasticity > 0f;
- if (flag2)
- {
- Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
- localToWorldMatrix.SetColumn(3, particle2.m_Position);
- bool flag3 = particle.m_Transform != null;
- Vector3 vector;
- if (flag3)
- {
- vector = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition);
- }
- else
- {
- vector = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset);
- }
- Vector3 vector2 = vector - particle.m_Position;
- particle.m_Position += vector2 * particle.m_Elasticity;
- bool flag4 = num > 0f;
- if (flag4)
- {
- vector2 = vector - particle.m_Position;
- float magnitude2 = vector2.magnitude;
- float num2 = magnitude * (1f - num) * 2f;
- bool flag5 = magnitude2 > num2;
- if (flag5)
- {
- particle.m_Position += vector2 * ((magnitude2 - num2) / magnitude2);
- }
- }
- }
- bool flag6 = this.m_Colliders != null;
- if (flag6)
- {
- float particleRadius = particle.m_Radius * this.m_ObjectScale;
- for (int j = 0; j < this.m_Colliders.Count; j++)
- {
- DynamicBoneCollider dynamicBoneCollider = this.m_Colliders[j];
- bool flag7 = dynamicBoneCollider != null && dynamicBoneCollider.enabled;
- if (flag7)
- {
- dynamicBoneCollider.Collide(ref particle.m_Position, particleRadius);
- }
- }
- }
- bool flag8 = this.m_FreezeAxis > DynamicBone.FreezeAxis.None;
- if (flag8)
- {
- switch (this.m_FreezeAxis)
- {
- case DynamicBone.FreezeAxis.X:
- plane.SetNormalAndPosition(particle2.m_Transform.right, particle2.m_Position);
- break;
- case DynamicBone.FreezeAxis.Y:
- plane.SetNormalAndPosition(particle2.m_Transform.up, particle2.m_Position);
- break;
- case DynamicBone.FreezeAxis.Z:
- plane.SetNormalAndPosition(particle2.m_Transform.forward, particle2.m_Position);
- break;
- }
- particle.m_Position -= plane.normal * plane.GetDistanceToPoint(particle.m_Position);
- }
- Vector3 vector3 = particle2.m_Position - particle.m_Position;
- float magnitude3 = vector3.magnitude;
- bool flag9 = magnitude3 > 0f;
- if (flag9)
- {
- particle.m_Position += vector3 * ((magnitude3 - magnitude) / magnitude3);
- }
- }
- }
-
- // Token: 0x06000013 RID: 19 RVA: 0x00003018 File Offset: 0x00001218
- private void SkipUpdateParticles()
- {
- for (int i = 0; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- bool flag = particle.m_ParentIndex >= 0;
- if (flag)
- {
- particle.m_PrevPosition += this.m_ObjectMove;
- particle.m_Position += this.m_ObjectMove;
- DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
- bool flag2 = particle.m_Transform != null;
- float magnitude;
- if (flag2)
- {
- magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude;
- }
- else
- {
- magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude;
- }
- float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight);
- bool flag3 = num > 0f;
- if (flag3)
- {
- Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
- localToWorldMatrix.SetColumn(3, particle2.m_Position);
- bool flag4 = particle.m_Transform != null;
- Vector3 vector;
- if (flag4)
- {
- vector = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition);
- }
- else
- {
- vector = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset);
- }
- Vector3 vector2 = vector - particle.m_Position;
- float magnitude2 = vector2.magnitude;
- float num2 = magnitude * (1f - num) * 2f;
- bool flag5 = magnitude2 > num2;
- if (flag5)
- {
- particle.m_Position += vector2 * ((magnitude2 - num2) / magnitude2);
- }
- }
- Vector3 vector3 = particle2.m_Position - particle.m_Position;
- float magnitude3 = vector3.magnitude;
- bool flag6 = magnitude3 > 0f;
- if (flag6)
- {
- particle.m_Position += vector3 * ((magnitude3 - magnitude) / magnitude3);
- }
- }
- else
- {
- particle.m_PrevPosition = particle.m_Position;
- particle.m_Position = particle.m_Transform.position;
- }
- }
- }
-
- // Token: 0x06000014 RID: 20 RVA: 0x00003254 File Offset: 0x00001454
- private void ApplyParticlesToTransforms()
- {
- for (int i = 1; i < this.m_Particles.Count; i++)
- {
- DynamicBone.Particle particle = this.m_Particles[i];
- DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
- bool flag = particle2.m_Transform.childCount <= 1;
- if (flag)
- {
- bool flag2 = particle.m_Transform != null;
- Vector3 vector;
- if (flag2)
- {
- vector = particle.m_Transform.localPosition;
- }
- else
- {
- vector = particle.m_EndOffset;
- }
- Quaternion quaternion = Quaternion.FromToRotation(particle2.m_Transform.TransformDirection(vector), particle.m_Position - particle2.m_Position);
- particle2.m_Transform.rotation = quaternion * particle2.m_Transform.rotation;
- }
- bool flag3 = particle.m_Transform != null;
- if (flag3)
- {
- particle.m_Transform.position = particle.m_Position;
- }
- }
- }
-
- // Token: 0x04000003 RID: 3
- public Transform m_Root = null;
-
- // Token: 0x04000004 RID: 4
- public float m_UpdateRate = 60f;
-
- // Token: 0x04000005 RID: 5
- [Range(0f, 1f)]
- public float m_Damping = 0.1f;
-
- // Token: 0x04000006 RID: 6
- public AnimationCurve m_DampingDistrib = null;
-
- // Token: 0x04000007 RID: 7
- [Range(0f, 1f)]
- public float m_Elasticity = 0.1f;
-
- // Token: 0x04000008 RID: 8
- public AnimationCurve m_ElasticityDistrib = null;
-
- // Token: 0x04000009 RID: 9
- [Range(0f, 1f)]
- public float m_Stiffness = 0.1f;
-
- // Token: 0x0400000A RID: 10
- public AnimationCurve m_StiffnessDistrib = null;
-
- // Token: 0x0400000B RID: 11
- [Range(0f, 1f)]
- public float m_Inert = 0f;
-
- // Token: 0x0400000C RID: 12
- public AnimationCurve m_InertDistrib = null;
-
- // Token: 0x0400000D RID: 13
- public float m_Radius = 0f;
-
- // Token: 0x0400000E RID: 14
- public AnimationCurve m_RadiusDistrib = null;
-
- // Token: 0x0400000F RID: 15
- public float m_EndLength = 0f;
-
- // Token: 0x04000010 RID: 16
- public Vector3 m_EndOffset = Vector3.zero;
-
- // Token: 0x04000011 RID: 17
- public Vector3 m_Gravity = Vector3.zero;
-
- // Token: 0x04000012 RID: 18
- public Vector3 m_Force = Vector3.zero;
-
- // Token: 0x04000013 RID: 19
- public List m_Colliders = null;
-
- // Token: 0x04000014 RID: 20
- public List m_Exclusions = null;
-
- // Token: 0x04000015 RID: 21
- public DynamicBone.FreezeAxis m_FreezeAxis = DynamicBone.FreezeAxis.None;
-
- // Token: 0x04000016 RID: 22
- public bool m_DistantDisable = false;
-
- // Token: 0x04000017 RID: 23
- public Transform m_ReferenceObject = null;
-
- // Token: 0x04000018 RID: 24
- public float m_DistanceToObject = 20f;
-
- // Token: 0x04000019 RID: 25
- private Vector3 m_LocalGravity = Vector3.zero;
-
- // Token: 0x0400001A RID: 26
- private Vector3 m_ObjectMove = Vector3.zero;
-
- // Token: 0x0400001B RID: 27
- private Vector3 m_ObjectPrevPosition = Vector3.zero;
-
- // Token: 0x0400001C RID: 28
- private float m_BoneTotalLength = 0f;
-
- // Token: 0x0400001D RID: 29
- private float m_ObjectScale = 1f;
-
- // Token: 0x0400001E RID: 30
- private float m_Time = 0f;
-
- // Token: 0x0400001F RID: 31
- private float m_Weight = 1f;
-
- // Token: 0x04000020 RID: 32
- private bool m_DistantDisabled = false;
-
- // Token: 0x04000021 RID: 33
- private List m_Particles = new List();
-
- // Token: 0x02000011 RID: 17
- public enum FreezeAxis
- {
- // Token: 0x0400006C RID: 108
- None,
- // Token: 0x0400006D RID: 109
- X,
- // Token: 0x0400006E RID: 110
- Y,
- // Token: 0x0400006F RID: 111
- Z
- }
-
- // Token: 0x02000012 RID: 18
- private class Particle
- {
- // Token: 0x04000070 RID: 112
- public Transform m_Transform = null;
-
- // Token: 0x04000071 RID: 113
- public int m_ParentIndex = -1;
-
- // Token: 0x04000072 RID: 114
- public float m_Damping = 0f;
-
- // Token: 0x04000073 RID: 115
- public float m_Elasticity = 0f;
-
- // Token: 0x04000074 RID: 116
- public float m_Stiffness = 0f;
-
- // Token: 0x04000075 RID: 117
- public float m_Inert = 0f;
-
- // Token: 0x04000076 RID: 118
- public float m_Radius = 0f;
-
- // Token: 0x04000077 RID: 119
- public float m_BoneLength = 0f;
-
- // Token: 0x04000078 RID: 120
- public Vector3 m_Position = Vector3.zero;
-
- // Token: 0x04000079 RID: 121
- public Vector3 m_PrevPosition = Vector3.zero;
-
- // Token: 0x0400007A RID: 122
- public Vector3 m_EndOffset = Vector3.zero;
-
- // Token: 0x0400007B RID: 123
- public Vector3 m_InitLocalPosition = Vector3.zero;
-
- // Token: 0x0400007C RID: 124
- public Quaternion m_InitLocalRotation = Quaternion.identity;
- }
-}
diff --git a/CustomSaber/DynamicBoneCollider.cs b/CustomSaber/DynamicBoneCollider.cs
deleted file mode 100644
index 42b261b..0000000
--- a/CustomSaber/DynamicBoneCollider.cs
+++ /dev/null
@@ -1,281 +0,0 @@
-using System;
-using UnityEngine;
-
-// Token: 0x02000004 RID: 4
-[AddComponentMenu("Dynamic Bone/Dynamic Bone Collider")]
-public class DynamicBoneCollider : MonoBehaviour
-{
- // Token: 0x06000016 RID: 22 RVA: 0x00003485 File Offset: 0x00001685
- private void OnValidate()
- {
- this.m_Radius = Mathf.Max(this.m_Radius, 0f);
- this.m_Height = Mathf.Max(this.m_Height, 0f);
- }
-
- // Token: 0x06000017 RID: 23 RVA: 0x000034B4 File Offset: 0x000016B4
- public void Collide(ref Vector3 particlePosition, float particleRadius)
- {
- float num = this.m_Radius * Mathf.Abs(base.transform.lossyScale.x);
- float num2 = this.m_Height * 0.5f - this.m_Radius;
- bool flag = num2 <= 0f;
- if (flag)
- {
- bool flag2 = this.m_Bound == DynamicBoneCollider.Bound.Outside;
- if (flag2)
- {
- DynamicBoneCollider.OutsideSphere(ref particlePosition, particleRadius, base.transform.TransformPoint(this.m_Center), num);
- }
- else
- {
- DynamicBoneCollider.InsideSphere(ref particlePosition, particleRadius, base.transform.TransformPoint(this.m_Center), num);
- }
- }
- else
- {
- Vector3 center = this.m_Center;
- Vector3 center2 = this.m_Center;
- switch (this.m_Direction)
- {
- case DynamicBoneCollider.Direction.X:
- center.x -= num2;
- center2.x += num2;
- break;
- case DynamicBoneCollider.Direction.Y:
- center.y -= num2;
- center2.y += num2;
- break;
- case DynamicBoneCollider.Direction.Z:
- center.z -= num2;
- center2.z += num2;
- break;
- }
- bool flag3 = this.m_Bound == DynamicBoneCollider.Bound.Outside;
- if (flag3)
- {
- DynamicBoneCollider.OutsideCapsule(ref particlePosition, particleRadius, base.transform.TransformPoint(center), base.transform.TransformPoint(center2), num);
- }
- else
- {
- DynamicBoneCollider.InsideCapsule(ref particlePosition, particleRadius, base.transform.TransformPoint(center), base.transform.TransformPoint(center2), num);
- }
- }
- }
-
- // Token: 0x06000018 RID: 24 RVA: 0x00003620 File Offset: 0x00001820
- private static void OutsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius)
- {
- float num = sphereRadius + particleRadius;
- float num2 = num * num;
- Vector3 vector = particlePosition - sphereCenter;
- float sqrMagnitude = vector.sqrMagnitude;
- bool flag = sqrMagnitude > 0f && sqrMagnitude < num2;
- if (flag)
- {
- float num3 = Mathf.Sqrt(sqrMagnitude);
- particlePosition = sphereCenter + vector * (num / num3);
- }
- }
-
- // Token: 0x06000019 RID: 25 RVA: 0x00003680 File Offset: 0x00001880
- private static void InsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius)
- {
- float num = sphereRadius + particleRadius;
- float num2 = num * num;
- Vector3 vector = particlePosition - sphereCenter;
- float sqrMagnitude = vector.sqrMagnitude;
- bool flag = sqrMagnitude > num2;
- if (flag)
- {
- float num3 = Mathf.Sqrt(sqrMagnitude);
- particlePosition = sphereCenter + vector * (num / num3);
- }
- }
-
- // Token: 0x0600001A RID: 26 RVA: 0x000036D8 File Offset: 0x000018D8
- private static void OutsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius)
- {
- float num = capsuleRadius + particleRadius;
- float num2 = num * num;
- Vector3 vector = capsuleP1 - capsuleP0;
- Vector3 vector2 = particlePosition - capsuleP0;
- float num3 = Vector3.Dot(vector2, vector);
- bool flag = num3 <= 0f;
- if (flag)
- {
- float sqrMagnitude = vector2.sqrMagnitude;
- bool flag2 = sqrMagnitude > 0f && sqrMagnitude < num2;
- if (flag2)
- {
- float num4 = Mathf.Sqrt(sqrMagnitude);
- particlePosition = capsuleP0 + vector2 * (num / num4);
- }
- }
- else
- {
- float sqrMagnitude2 = vector.sqrMagnitude;
- bool flag3 = num3 >= sqrMagnitude2;
- if (flag3)
- {
- vector2 = particlePosition - capsuleP1;
- float sqrMagnitude3 = vector2.sqrMagnitude;
- bool flag4 = sqrMagnitude3 > 0f && sqrMagnitude3 < num2;
- if (flag4)
- {
- float num5 = Mathf.Sqrt(sqrMagnitude3);
- particlePosition = capsuleP1 + vector2 * (num / num5);
- }
- }
- else
- {
- bool flag5 = sqrMagnitude2 > 0f;
- if (flag5)
- {
- num3 /= sqrMagnitude2;
- vector2 -= vector * num3;
- float sqrMagnitude4 = vector2.sqrMagnitude;
- bool flag6 = sqrMagnitude4 > 0f && sqrMagnitude4 < num2;
- if (flag6)
- {
- float num6 = Mathf.Sqrt(sqrMagnitude4);
- particlePosition += vector2 * ((num - num6) / num6);
- }
- }
- }
- }
- }
-
- // Token: 0x0600001B RID: 27 RVA: 0x00003844 File Offset: 0x00001A44
- private static void InsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius)
- {
- float num = capsuleRadius + particleRadius;
- float num2 = num * num;
- Vector3 vector = capsuleP1 - capsuleP0;
- Vector3 vector2 = particlePosition - capsuleP0;
- float num3 = Vector3.Dot(vector2, vector);
- bool flag = num3 <= 0f;
- if (flag)
- {
- float sqrMagnitude = vector2.sqrMagnitude;
- bool flag2 = sqrMagnitude > num2;
- if (flag2)
- {
- float num4 = Mathf.Sqrt(sqrMagnitude);
- particlePosition = capsuleP0 + vector2 * (num / num4);
- }
- }
- else
- {
- float sqrMagnitude2 = vector.sqrMagnitude;
- bool flag3 = num3 >= sqrMagnitude2;
- if (flag3)
- {
- vector2 = particlePosition - capsuleP1;
- float sqrMagnitude3 = vector2.sqrMagnitude;
- bool flag4 = sqrMagnitude3 > num2;
- if (flag4)
- {
- float num5 = Mathf.Sqrt(sqrMagnitude3);
- particlePosition = capsuleP1 + vector2 * (num / num5);
- }
- }
- else
- {
- bool flag5 = sqrMagnitude2 > 0f;
- if (flag5)
- {
- num3 /= sqrMagnitude2;
- vector2 -= vector * num3;
- float sqrMagnitude4 = vector2.sqrMagnitude;
- bool flag6 = sqrMagnitude4 > num2;
- if (flag6)
- {
- float num6 = Mathf.Sqrt(sqrMagnitude4);
- particlePosition += vector2 * ((num - num6) / num6);
- }
- }
- }
- }
- }
-
- // Token: 0x0600001C RID: 28 RVA: 0x0000398C File Offset: 0x00001B8C
- private void OnDrawGizmosSelected()
- {
- bool flag = !base.enabled;
- if (!flag)
- {
- bool flag2 = this.m_Bound == DynamicBoneCollider.Bound.Outside;
- if (flag2)
- {
- Gizmos.color = Color.yellow;
- }
- else
- {
- Gizmos.color = Color.magenta;
- }
- float num = this.m_Radius * Mathf.Abs(base.transform.lossyScale.x);
- float num2 = this.m_Height * 0.5f - this.m_Radius;
- bool flag3 = num2 <= 0f;
- if (flag3)
- {
- Gizmos.DrawWireSphere(base.transform.TransformPoint(this.m_Center), num);
- }
- else
- {
- Vector3 center = this.m_Center;
- Vector3 center2 = this.m_Center;
- switch (this.m_Direction)
- {
- case DynamicBoneCollider.Direction.X:
- center.x -= num2;
- center2.x += num2;
- break;
- case DynamicBoneCollider.Direction.Y:
- center.y -= num2;
- center2.y += num2;
- break;
- case DynamicBoneCollider.Direction.Z:
- center.z -= num2;
- center2.z += num2;
- break;
- }
- Gizmos.DrawWireSphere(base.transform.TransformPoint(center), num);
- Gizmos.DrawWireSphere(base.transform.TransformPoint(center2), num);
- }
- }
- }
-
- // Token: 0x04000022 RID: 34
- public Vector3 m_Center = Vector3.zero;
-
- // Token: 0x04000023 RID: 35
- public float m_Radius = 0.5f;
-
- // Token: 0x04000024 RID: 36
- public float m_Height = 0f;
-
- // Token: 0x04000025 RID: 37
- public DynamicBoneCollider.Direction m_Direction = DynamicBoneCollider.Direction.X;
-
- // Token: 0x04000026 RID: 38
- public DynamicBoneCollider.Bound m_Bound = DynamicBoneCollider.Bound.Outside;
-
- // Token: 0x02000013 RID: 19
- public enum Direction
- {
- // Token: 0x0400007E RID: 126
- X,
- // Token: 0x0400007F RID: 127
- Y,
- // Token: 0x04000080 RID: 128
- Z
- }
-
- // Token: 0x02000014 RID: 20
- public enum Bound
- {
- // Token: 0x04000082 RID: 130
- Outside,
- // Token: 0x04000083 RID: 131
- Inside
- }
-}
diff --git a/CustomSaber/EventFilterBehaviour.cs b/CustomSaber/EventFilterBehaviour.cs
deleted file mode 100644
index 2b55b80..0000000
--- a/CustomSaber/EventFilterBehaviour.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using UnityEngine;
-
-namespace CustomSaber
-{
- [RequireComponent(typeof(EventManager))]
- public class EventFilterBehaviour : MonoBehaviour
- {
- protected EventManager EventManager
- {
- get
- {
- if (_eventManager == null)
- {
- _eventManager = GetComponent();
- }
- return _eventManager;
- }
- }
-
- private EventManager _eventManager;
- }
-}
diff --git a/CustomSaber/EventFilters.cs b/CustomSaber/EventFilters.cs
deleted file mode 100644
index 71bbcf8..0000000
--- a/CustomSaber/EventFilters.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using UnityEngine.Events;
-
-namespace CustomSaber
-{
- public class EveryNthComboFilter : EventFilterBehaviour
- {
- public int ComboStep = 50;
- public UnityEvent NthComboReached;
- private void OnEnable()
- {
- EventManager.OnComboChanged.AddListener(OnComboStep);
- }
- private void OnDisable()
- {
- EventManager.OnComboChanged.RemoveListener(OnComboStep);
- }
-
- private void OnComboStep(int combo)
- {
- if (combo % ComboStep == 0 && combo != 0)
- {
- NthComboReached.Invoke();
- }
- }
- }
-
- public class ComboReachedEvent : EventFilterBehaviour
- {
- public int ComboTarget = 50;
- public UnityEvent NthComboReached;
-
- private void OnEnable()
- {
- EventManager.OnComboChanged.AddListener(OnComboReached);
- }
-
- private void OnDisable()
- {
- EventManager.OnComboChanged.RemoveListener(OnComboReached);
- }
-
- private void OnComboReached(int combo)
- {
- if (combo == ComboTarget)
- {
- NthComboReached.Invoke();
- }
- }
- }
-}
diff --git a/CustomSaber/EventManager.cs b/CustomSaber/EventManager.cs
deleted file mode 100644
index 524355c..0000000
--- a/CustomSaber/EventManager.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using UnityEngine;
-using UnityEngine.Events;
-
-namespace CustomSaber
-{
- public class EventManager : MonoBehaviour
- {
- public UnityEvent OnSlice;
- public UnityEvent OnComboBreak;
- public UnityEvent MultiplierUp;
- public UnityEvent SaberStartColliding;
- public UnityEvent SaberStopColliding;
- public UnityEvent OnLevelStart;
- public UnityEvent OnLevelFail;
- public UnityEvent OnLevelEnded;
- public UnityEvent OnBlueLightOn;
- public UnityEvent OnRedLightOn;
-
- [Serializable]
- public class ComboChangedEvent : UnityEvent
- {
- }
-
- public ComboChangedEvent OnComboChanged = new ComboChangedEvent();
- }
-}
\ No newline at end of file
diff --git a/CustomSaber/GameHooks.cs b/CustomSaber/GameHooks.cs
deleted file mode 100644
index e540cf7..0000000
--- a/CustomSaber/GameHooks.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Harmony;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using UnityEngine.SceneManagement;
-
-namespace CustomSaber.Harmony_Patches
-{
- [HarmonyPatch(typeof(SceneManager), "Internal_SceneLoaded",
- new Type[] { typeof(Scene), typeof(LoadSceneMode) })]
- class SceneLoadedHooks
- {
-
- public static bool Prefix(Scene scene, LoadSceneMode mode)
- {
- if (scene.name == "GameCore")
- {
- Console.WriteLine($"Blocked scene {scene.name} from firing sceneLoaded event!");
- return false;
- }
- return true;
- }
-
- }
-
- // [HarmonyPatch(typeof(SceneManager), "Internal_ActiveSceneChanged",
- //new Type[] { typeof(Scene), typeof(Scene) })]
- // class ActiveSceneChangedHooks
- // {
- // public static bool Prefix(Scene previousActiveScene, Scene newActiveScene)
- // {
- // if (newActiveScene.name == "GameCore")
- // {
- // Console.WriteLine($"Blocked scene {newActiveScene.name} from firing activeSceneChanged event!");
- // return false;
- // }
- // return true;
- // }
-
- // }
-}
diff --git a/CustomSaber/Logger.cs b/CustomSaber/Logger.cs
new file mode 100644
index 0000000..cc39785
--- /dev/null
+++ b/CustomSaber/Logger.cs
@@ -0,0 +1,9 @@
+using IPALogger = IPA.Logging.Logger;
+
+namespace CustomSaber
+{
+ internal static class Logger
+ {
+ public static IPALogger log { get; set; }
+ }
+}
diff --git a/CustomSaber/Plugin.cs b/CustomSaber/Plugin.cs
index ad6d1e4..5cbc56e 100644
--- a/CustomSaber/Plugin.cs
+++ b/CustomSaber/Plugin.cs
@@ -1,208 +1,69 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Collections;
-using System.Text;
-using IllusionPlugin;
-using UnityEngine;
-using UnityEngine.SceneManagement;
+using CustomSaber.Settings;
+using CustomSaber.Settings.UI;
+using CustomSaber.Utilities;
+using IPA;
+using IPA.Config;
+using IPA.Loader;
+using IPA.Utilities;
using System.IO;
-using Harmony;
-using System.Reflection;
+using IPALogger = IPA.Logging.Logger;
namespace CustomSaber
{
- public class Plugin : IPlugin
+ [Plugin(RuntimeOptions.SingleStartInit)]
+ public class Plugin
{
- public string Name
- {
- get { return "Saber Mod"; }
- }
-
- public string Version
- {
- get { return "2.7.0"; }
- }
-
- private static List _saberPaths;
- private static AssetBundle _currentSaber;
- public static string _currentSaberPath;
- public static Saber LeftSaber;
- public static Saber RightSaber;
-
- private bool _init;
-
- public void OnApplicationStart()
- {
- if (_init) return;
- _init = true;
-
- Console.WriteLine($"Custom Sabers v{Version} loaded!");
-
- SceneManager.activeSceneChanged += SceneManagerOnActiveSceneChanged;
-
- var sabers = RetrieveCustomSabers();
- if (sabers.Count == 0)
- {
- Console.WriteLine("No custom sabers found.");
- return;
- }
-
- _currentSaberPath = PlayerPrefs.GetString("lastSaber", null);
- if (_currentSaberPath == null || !sabers.Contains(_currentSaberPath))
- {
- _currentSaberPath = sabers[0];
- }
- }
+ public static string PluginName => "Custom Sabers";
+ public static SemVer.Version PluginVersion { get; private set; } = new SemVer.Version("0.0.0"); // Default.
+ public static string PluginAssetPath => Path.Combine(UnityGame.InstallPath, "CustomSabers");
- public void OnApplicationQuit()
- {
- SceneManager.activeSceneChanged -= SceneManagerOnActiveSceneChanged;
- }
-
- bool FirstFetch = true;
- private void SceneManagerOnActiveSceneChanged(Scene arg0, Scene scene)
+ [Init]
+ public void Init(IPALogger logger, Config config, PluginMetadata metadata)
{
- if (scene.buildIndex > 0)
- {
- if (FirstFetch)
- {
- Console.WriteLine("Launching coroutine to grab original sabers!");
- SharedCoroutineStarter.instance.StartCoroutine(PreloadDefaultSabers());
- Console.WriteLine("Launched!");
- }
- }
-
- if (scene.name == "GameCore")
- {
- LoadNewSaber(_currentSaberPath);
- SaberScript.LoadAssets();
- }
+ Logger.log = logger;
+ Configuration.Init(config);
- if (scene.name == "Menu")
+ if (metadata != null)
{
- if (_currentSaber != null)
- {
- _currentSaber.Unload(true);
- }
- CustomSaberUI.OnLoad();
+ PluginVersion = metadata.Version;
}
}
-
- private IEnumerator PreloadDefaultSabers()
- {
- FirstFetch = false;
- Console.WriteLine("Preloading default sabers!");
- var harmony = HarmonyInstance.Create("CustomSaberHarmonyInstance");
- harmony.PatchAll(Assembly.GetExecutingAssembly());
- Console.WriteLine("Loading GameCore scene");
- SceneManager.LoadSceneAsync("GameCore", LoadSceneMode.Additive);
- Console.WriteLine("Loaded!");
- yield return new WaitUntil(() => Resources.FindObjectsOfTypeAll().Count() > 1);
- Console.WriteLine("Got sabers!");
- foreach (Saber s in Resources.FindObjectsOfTypeAll())
- {
- Console.WriteLine($"Saber: {s.name}, GameObj: {s.gameObject.name}, {s.ToString()}");
- if (s.name == "LeftSaber") LeftSaber = Saber.Instantiate(s);
- else if (s.name == "RightSaber") RightSaber = Saber.Instantiate(s);
- }
- Console.WriteLine("Finished! Got default sabers! Setting active state");
- if (LeftSaber) { UnityEngine.Object.DontDestroyOnLoad(LeftSaber.gameObject); LeftSaber.gameObject.SetActive(false); LeftSaber.name = "___OriginalSaberPreviewB"; }
- if (RightSaber) { UnityEngine.Object.DontDestroyOnLoad(RightSaber.gameObject); RightSaber.gameObject.SetActive(false); RightSaber.name = "___OriginalSaberPreviewA"; }
- Console.WriteLine("Unloading GameCore");
- SceneManager.UnloadSceneAsync("GameCore");
- Console.WriteLine("Unloading harmony patches");
- harmony.UnpatchAll("CustomSaberHarmonyInstance");
- }
-
- public static List RetrieveCustomSabers()
- {
- _saberPaths = (Directory.GetFiles(Path.Combine(Application.dataPath, "../CustomSabers/"),
- "*.saber", SearchOption.AllDirectories).ToList());
- Console.WriteLine("Found " + _saberPaths.Count + " sabers");
- _saberPaths.Insert(0, "DefaultSabers");
- return _saberPaths;
- }
+ [OnStart]
+ public void OnApplicationStart() => Load();
+ [OnExit]
+ public void OnApplicationQuit() => Unload();
- public void OnUpdate()
+ private void OnGameSceneLoaded()
{
- if (_currentSaber == null) return;
- if (Input.GetKeyDown(KeyCode.Space))
- {
- RetrieveCustomSabers();
- if (_saberPaths.Count == 1) return;
- var oldIndex = _saberPaths.IndexOf(_currentSaberPath);
- if (oldIndex >= _saberPaths.Count - 1)
- {
- oldIndex = -1;
- }
-
- var newSaber = _saberPaths[oldIndex + 1];
- LoadNewSaber(newSaber);
- if (SceneManager.GetActiveScene().buildIndex != 4) return;
- SaberScript.LoadAssets();
- }
- else if (Input.GetKeyDown(KeyCode.Space) && Input.GetKey(KeyCode.LeftAlt))
- {
- RetrieveCustomSabers();
- if (_saberPaths.Count == 1) return;
- var oldIndex = _saberPaths.IndexOf(_currentSaberPath);
- if (oldIndex <= 0)
- {
- oldIndex = _saberPaths.Count - 1;
- }
-
- var newSaber = _saberPaths[oldIndex - 1];
- LoadNewSaber(newSaber);
- if (SceneManager.GetActiveScene().buildIndex != 4) return;
- SaberScript.LoadAssets();
- }
+ SaberScript.Load();
}
- public static void LoadNewSaber(string path)
+ private void Load()
{
- if (_currentSaber != null)
- {
- _currentSaber.Unload(true);
- }
-
- if (path != "DefaultSabers")
- {
- _currentSaberPath = path;
-
- _currentSaber =
- AssetBundle.LoadFromFile(_currentSaberPath);
- Console.WriteLine(_currentSaber.GetAllAssetNames()[0]);
- if (_currentSaber == null)
- {
- Console.WriteLine("something went wrong getting the asset bundle");
- }
- else
- {
- Console.WriteLine("Succesfully obtained the asset bundle!");
- SaberScript.CustomSaber = _currentSaber;
- }
- }
-
- PlayerPrefs.SetString("lastSaber", _currentSaberPath);
- Console.WriteLine($"Loaded saber {path}");
+ Configuration.Load();
+ SaberAssetLoader.Load();
+ SettingsUI.CreateMenu();
+ AddEvents();
+ Logger.log.Info($"{PluginName} v.{PluginVersion} has started.");
}
- public void OnFixedUpdate()
+ private void Unload()
{
-
+ Configuration.Save();
+ SaberAssetLoader.Clear();
+ RemoveEvents();
}
- public void OnLevelWasInitialized(int level)
+ private void AddEvents()
{
-
-
+ RemoveEvents();
+ BS_Utils.Utilities.BSEvents.gameSceneLoaded += OnGameSceneLoaded;
}
- public void OnLevelWasLoaded(int level)
+ private void RemoveEvents()
{
-
+ BS_Utils.Utilities.BSEvents.gameSceneLoaded -= OnGameSceneLoaded;
}
}
}
diff --git a/CustomSaber/Properties/AssemblyInfo.cs b/CustomSaber/Properties/AssemblyInfo.cs
index 1ce3f3f..bab2435 100644
--- a/CustomSaber/Properties/AssemblyInfo.cs
+++ b/CustomSaber/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -32,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.6.0.0")]
-[assembly: AssemblyFileVersion("2.6.0.0")]
+[assembly: AssemblyVersion("4.4.2")]
+[assembly: AssemblyFileVersion("4.4.2")]
diff --git a/CustomSaber/Resources/DefaultSabers/caeden.png b/CustomSaber/Resources/DefaultSabers/caeden.png
new file mode 100644
index 0000000..3fe0895
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/caeden.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/danike.png b/CustomSaber/Resources/DefaultSabers/danike.png
new file mode 100644
index 0000000..3b30d01
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/danike.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/default.png b/CustomSaber/Resources/DefaultSabers/default.png
new file mode 100644
index 0000000..30b5504
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/default.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/klouder.png b/CustomSaber/Resources/DefaultSabers/klouder.png
new file mode 100644
index 0000000..37da46f
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/klouder.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/kyle.png b/CustomSaber/Resources/DefaultSabers/kyle.png
new file mode 100644
index 0000000..82cf6df
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/kyle.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/lolpants.png b/CustomSaber/Resources/DefaultSabers/lolpants.png
new file mode 100644
index 0000000..209ec74
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/lolpants.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/meg-sabers.png b/CustomSaber/Resources/DefaultSabers/meg-sabers.png
new file mode 100644
index 0000000..86c417d
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/meg-sabers.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/ninja-simple-150.png b/CustomSaber/Resources/DefaultSabers/ninja-simple-150.png
new file mode 100644
index 0000000..65bc4b2
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/ninja-simple-150.png differ
diff --git a/CustomSaber/Resources/DefaultSabers/sobble.png b/CustomSaber/Resources/DefaultSabers/sobble.png
new file mode 100644
index 0000000..95eaee0
Binary files /dev/null and b/CustomSaber/Resources/DefaultSabers/sobble.png differ
diff --git a/CustomSaber/Resources/description.md b/CustomSaber/Resources/description.md
new file mode 100644
index 0000000..6682708
--- /dev/null
+++ b/CustomSaber/Resources/description.md
@@ -0,0 +1,4 @@
+Custom Sabers
+=====
+
+### A plugin that allows for replacing the default Beat Saber sabers.
\ No newline at end of file
diff --git a/CustomSaber/Resources/fa-magic-error.png b/CustomSaber/Resources/fa-magic-error.png
new file mode 100644
index 0000000..ac9d2af
Binary files /dev/null and b/CustomSaber/Resources/fa-magic-error.png differ
diff --git a/CustomSaber/Resources/fa-magic.png b/CustomSaber/Resources/fa-magic.png
new file mode 100644
index 0000000..41c36ba
Binary files /dev/null and b/CustomSaber/Resources/fa-magic.png differ
diff --git a/CustomSaber/Resources/icon.png b/CustomSaber/Resources/icon.png
new file mode 100644
index 0000000..dcab877
Binary files /dev/null and b/CustomSaber/Resources/icon.png differ
diff --git a/CustomSaber/SaberDescriptor.cs b/CustomSaber/SaberDescriptor.cs
deleted file mode 100644
index b640819..0000000
--- a/CustomSaber/SaberDescriptor.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
-public class SaberDescriptor : MonoBehaviour
-{
-
- public string SaberName = "saber";
- public string AuthorName = "author";
-}
\ No newline at end of file
diff --git a/CustomSaber/SaberScript.cs b/CustomSaber/SaberScript.cs
deleted file mode 100644
index 223d1d7..0000000
--- a/CustomSaber/SaberScript.cs
+++ /dev/null
@@ -1,470 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using UnityEngine;
-using System.Collections;
-using UnityEngine.SceneManagement;
-using System.IO;
-using Object = UnityEngine.Object;
-
-namespace CustomSaber
-{
- class SaberScript : MonoBehaviour
- {
- private enum AudioEvent
- {
- Play,
- Stop
- };
-
- public static AssetBundle CustomSaber;
-
- public static SaberScript Instance;
-
- private GameObject _leftTop;
- private GameObject _rightTop;
-
- private Vector3 _leftTopLocation;
- private Vector3 _rightTopLocation;
-
- private EventManager _leftEventManager;
- private EventManager _rightEventManager;
-
- private GameObject _leftSaber;
- private GameObject _rightSaber;
- private GameObject _saberRoot;
-
- private int LastNoteId;
-
- private BeatmapObjectSpawnController _beatmapObjectSpawnController;
- private ScoreController _scoreController;
- private ObstacleSaberSparkleEffectManager _saberCollisionManager;
- private GameEnergyCounter _gameEnergyCounter;
- private BeatmapObjectCallbackController _beatmapCallback;
- private GamePauseManager _gamePauseManager;
- private PlayerHeadAndObstacleInteraction _playerHeadAndObstacleInteraction;
-
- private bool _playerHeadWasInObstacle;
-
- public static void LoadAssets()
- {
- if (CustomSaber == null)
- {
- Console.WriteLine("SABER ASSET BUNDLE DOESNT EXIST");
- }
- else
- {
- if (Instance != null)
- {
- Destroy(Instance._leftSaber);
- Destroy(Instance._rightSaber);
- Destroy(Instance._saberRoot);
- Destroy(Instance.gameObject);
- }
- var loader = new GameObject("Saber Loader");
- Instance = loader.AddComponent();
- }
- }
-
- public void Restart()
- {
- CancelInvoke("_Restart");
- Invoke("_Restart", 0.5f);
- }
-
- private void _Restart()
- {
- OnDestroy();
- AddEvents();
- }
-
- private void SceneManagerOnSceneLoaded(Scene newScene, LoadSceneMode mode)
- {
- Restart();
- }
-
- private void Start()
- {
- LastNoteId = -1;
- Restart();
- }
-
- StandardLevelSceneSetup GetGameSceneSetup()
- {
- StandardLevelSceneSetup s = GameObject.FindObjectOfType();
- if (s == null)
- {
- s = UnityEngine.Resources.FindObjectsOfTypeAll().FirstOrDefault();
- }
- return s;
- }
-
- private void AddEvents()
- {
- _leftEventManager = _leftSaber.GetComponent();
- if (_leftEventManager == null)
- _leftEventManager = _leftSaber.AddComponent();
-
- _rightEventManager = _rightSaber.GetComponent();
- if (_rightEventManager == null)
- _rightEventManager = _rightSaber.AddComponent();
-
- _leftEventManager.OnLevelStart.Invoke();
- _rightEventManager.OnLevelStart.Invoke();
- try
- {
- _beatmapObjectSpawnController = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_beatmapObjectSpawnController == null)
- {
- Console.WriteLine("SPAWN CONTROLLER NULL");
- //_beatmapObjectSpawnController = _saberRoot.AddComponent();
- }
- _scoreController = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_scoreController == null)
- {
- Console.WriteLine("SCORE CONTROLLER NULL");
- //_scoreController = _saberRoot.AddComponent();
- }
- _saberCollisionManager =
- Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_saberCollisionManager == null)
- {
- Console.WriteLine("COLLISION MANAGER NULL");
- //_saberCollisionManager = _saberRoot.AddComponent();
- }
- _gameEnergyCounter = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_gameEnergyCounter == null)
- {
- Console.WriteLine("energery counter null");
- //_gameEnergyCounter = _saberRoot.AddComponent();
- }
- _beatmapCallback = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_beatmapCallback == null)
- {
- Console.WriteLine("BEATMAP CALLBACK NULL");
- //_beatmapCallback = _saberRoot.AddComponent();
- }
-
- _gamePauseManager = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_gamePauseManager == null)
- {
- Console.WriteLine("GamePauseManager Null");
- //_gamePauseManager = _saberRoot.AddComponent();
- }
-
- _playerHeadAndObstacleInteraction = Resources.FindObjectsOfTypeAll().FirstOrDefault();
- if (_playerHeadAndObstacleInteraction == null)
- {
- Console.WriteLine("PlayerHeadAndObstacleInteraction Null");
- //_playerHeadAndObstacleInteraction = _saberRoot.AddComponent();
- }
-
- _beatmapObjectSpawnController.noteWasCutEvent += SliceCallBack;
- _beatmapObjectSpawnController.noteWasMissedEvent += NoteMissCallBack;
- _scoreController.multiplierDidChangeEvent += MultiplierCallBack;
- _scoreController.comboDidChangeEvent += ComboChangeEvent;
-
- _saberCollisionManager.sparkleEffectDidStartEvent += SaberStartCollide;
- _saberCollisionManager.sparkleEffectDidEndEvent += SaberEndCollide;
-
- _gameEnergyCounter.gameEnergyDidReach0Event += FailLevelCallBack;
-
- _beatmapCallback.beatmapEventDidTriggerEvent += LightEventCallBack;
- // ReflectionUtil.SetPrivateField(_gamePauseManager, "_gameDidResumeSignal", (Action)OnPauseMenuClosed); //For some reason _gameDidResumeSignal isn't public.
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- Console.WriteLine(e.Message);
- throw;
- }
-
- try
- {
- StandardLevelSceneSetup mgs = GetGameSceneSetup();
- BeatmapData beatmapData = mgs.standardLevelSceneSetupData.difficultyBeatmap.beatmapData;
-
- BeatmapLineData[] beatmapLinesData = beatmapData.beatmapLinesData;
- float LastTime = 0.0f;
-
- for (int i = 0; i < beatmapLinesData.Length; i++)
- {
- BeatmapObjectData[] beatmapObjectsData = beatmapLinesData[i].beatmapObjectsData;
- for (int j = beatmapObjectsData.Length - 1; j > 0; j--)
- {
- if (beatmapObjectsData[j].beatmapObjectType == BeatmapObjectType.Note)
- {
- if (((NoteData)beatmapObjectsData[j]).noteType != NoteType.Bomb)
- {
- if (beatmapObjectsData[j].time > LastTime)
- {
- LastNoteId = beatmapObjectsData[j].id;
- LastTime = beatmapObjectsData[j].time;
- }
- break;
- }
- }
- }
- }
-
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- Console.WriteLine(e.Message);
- throw;
- }
-
- }
-
- private void OnDestroy()
- {
- if (_scoreController == null) return;
- _beatmapObjectSpawnController.noteWasCutEvent -= SliceCallBack;
- _beatmapObjectSpawnController.noteWasMissedEvent -= NoteMissCallBack;
- _scoreController.multiplierDidChangeEvent -= MultiplierCallBack;
- _scoreController.comboDidChangeEvent -= ComboChangeEvent;
-
- _saberCollisionManager.sparkleEffectDidStartEvent -= SaberStartCollide;
- _saberCollisionManager.sparkleEffectDidEndEvent -= SaberEndCollide;
-
- _gameEnergyCounter.gameEnergyDidReach0Event -= FailLevelCallBack;
- _beatmapCallback.beatmapEventDidTriggerEvent -= LightEventCallBack;
- }
-
- void Awake()
- {
- _leftTopLocation = Vector3.zero;
- _rightTopLocation = Vector3.zero;
-
- Console.WriteLine("Replacing sabers");
- if (CustomSaber == null)
- {
- Console.WriteLine("Assets Bundle is null");
- return;
- }
-
- GameObject saberRoot = CustomSaber.LoadAsset("_customsaber");
-
- if (saberRoot != null)
- {
- Console.WriteLine(saberRoot.GetComponent().SaberName);
- _saberRoot = Instantiate(saberRoot);
- _rightSaber = _saberRoot.transform.Find("RightSaber").gameObject;
- _leftSaber = _saberRoot.transform.Find("LeftSaber").gameObject;
- }
- StartCoroutine(WaitForSabers(saberRoot));
- }
-
- private IEnumerator WaitForSabers(GameObject saberRoot)
- {
- yield return new WaitUntil(() => Resources.FindObjectsOfTypeAll().Any());
-
- var sabers = Resources.FindObjectsOfTypeAll();
- Console.WriteLine("Saber list get: " + sabers.Length);
- foreach (var saber in sabers)
- {
- Console.WriteLine(saber.saberType + " " + saber.transform.GetChild(0) + saber.transform.GetChild(1) + saber.transform.GetChild(2) + saber.transform.GetChild(3));
- var handle = saber.transform.Find("Bottom");
- var blade = saber.transform.Find("Saber");
- var top = saber.transform.Find("Top");
-
- Console.WriteLine("Saber Transform Found");
-
- foreach (Transform t in saber.transform)
- {
- var filter = t.GetComponentInChildren();
- if (filter) filter.sharedMesh = null;
-
- foreach (Transform t2 in t)
- {
- filter = t2.GetComponentInChildren();
- if (filter) filter.sharedMesh = null;
- }
- }
-
- blade.transform.localRotation = Quaternion.identity;
- blade.transform.localScale = new Vector3(1, 1, 1);
- blade.transform.localPosition = new Vector3(0, -0.01f, 0);
- handle.gameObject.SetActive(false);
-
- CustomTrail[] trails;
-
- if (saber.saberType == Saber.SaberType.SaberB)
- {
- if (saberRoot == null) { }
- else
- _rightSaber.transform.parent = blade.transform;
- _rightSaber.transform.position = saber.transform.position;
- _rightSaber.transform.rotation = saber.transform.rotation;
- _rightTop = top.gameObject;
-
- trails = _rightSaber.GetComponents();
- foreach (CustomTrail trail in trails)
- {
- trail.Init(saber);
- }
- }
- else if (saber.saberType == Saber.SaberType.SaberA)
- {
- if (saberRoot == null) { }
- else
- _leftSaber.transform.parent = blade.transform;
- _leftSaber.transform.position = saber.transform.position;
- _leftSaber.transform.rotation = saber.transform.rotation;
- _leftTop = top.gameObject;
-
- trails = _leftSaber.GetComponents();
- foreach (CustomTrail trail in trails)
- {
- trail.Init(saber);
- }
- }
- }
- }
-
- private void OnPauseMenuClosed()
- {
- StartCoroutine(WaitForSabers(_saberRoot));
- }
-
- private void Update()
- {
- if (_playerHeadAndObstacleInteraction != null)
- {
- if (_playerHeadAndObstacleInteraction.intersectingObstacles.Count > 0)
- {
- if (!_playerHeadWasInObstacle)
- {
- if (_leftEventManager != null && _rightEventManager != null)
- {
- _leftEventManager.OnComboBreak.Invoke();
- _rightEventManager.OnComboBreak.Invoke();
- }
- _playerHeadWasInObstacle = true;
- }
- else
- {
- _playerHeadWasInObstacle = false;
- }
- }
- }
-
- /*Vector3 LeftVelocity = LeftTop.transform.position - LeftTopLocation;
- Vector3 RightVelocity = RightTop.transform.position - RightTopLocation;
-
- Shader.SetGlobalColor("LeftSaberVelocity", new Color(LeftVelocity.x, LeftVelocity.y, LeftVelocity.z, 0.0f));
- Shader.SetGlobalColor("RightSaberVelocity", new Color(RightVelocity.x, RightVelocity.y, RightVelocity.z, 0.0f));
-
- LeftTopLocation = LeftTop.transform.position;
- RightTopLocation = RightTop.transform.position;*/
- }
-
- private void SliceCallBack(BeatmapObjectSpawnController beatmapObjectSpawnController, NoteController noteController, NoteCutInfo noteCutInfo)
- {
- if (!noteCutInfo.allIsOK)
- {
- _leftEventManager.OnComboBreak.Invoke();
- _rightEventManager.OnComboBreak.Invoke();
- }
- else
- {
- if (noteCutInfo.saberType == Saber.SaberType.SaberA)
- {
- _leftEventManager.OnSlice.Invoke();
- }
- else if (noteCutInfo.saberType == Saber.SaberType.SaberB)
- {
- _rightEventManager.OnSlice.Invoke();
- }
- }
-
- if (noteController.noteData.id == LastNoteId)
- {
- _leftEventManager.OnLevelEnded.Invoke();
- _rightEventManager.OnLevelEnded.Invoke();
-
- }
- }
-
- private void NoteMissCallBack(BeatmapObjectSpawnController beatmapObjectSpawnController, NoteController noteController)
- {
-
- if (noteController.noteData.noteType != NoteType.Bomb)
- {
- _leftEventManager.OnComboBreak.Invoke();
- _rightEventManager.OnComboBreak.Invoke();
- }
-
- if (noteController.noteData.id == LastNoteId)
- {
- _leftEventManager.OnLevelEnded.Invoke();
- _rightEventManager.OnLevelEnded.Invoke();
- }
- }
-
- private void MultiplierCallBack(int multiplier, float progress)
- {
- if (multiplier > 1 && progress < 0.1f)
- {
- _leftEventManager.MultiplierUp.Invoke();
- _rightEventManager.MultiplierUp.Invoke();
- }
- }
-
- private void SaberStartCollide(Saber.SaberType saber)
- {
- if (saber == Saber.SaberType.SaberA)
- {
- _leftEventManager.SaberStartColliding.Invoke();
- }
- else if (saber == Saber.SaberType.SaberB)
- {
- _rightEventManager.SaberStartColliding.Invoke();
- }
- }
-
- private void SaberEndCollide(Saber.SaberType saber)
- {
- if (saber == Saber.SaberType.SaberA)
- {
- _leftEventManager.SaberStopColliding.Invoke();
- }
- else if (saber == Saber.SaberType.SaberB)
- {
- _rightEventManager.SaberStopColliding.Invoke();
- }
- }
-
- private void FailLevelCallBack()
- {
- _leftEventManager.OnLevelFail.Invoke();
- _rightEventManager.OnLevelFail.Invoke();
- }
-
- private void LightEventCallBack(BeatmapEventData songEvent)
- {
- if ((int)songEvent.type < 5)
- {
- if (songEvent.value > 0 && songEvent.value < 4)
- {
- _leftEventManager.OnBlueLightOn.Invoke();
- _rightEventManager.OnBlueLightOn.Invoke();
- }
-
- if (songEvent.value > 4 && songEvent.value < 8)
- {
- _leftEventManager.OnRedLightOn.Invoke();
- _rightEventManager.OnRedLightOn.Invoke();
- }
- }
- }
-
- private void ComboChangeEvent(int combo)
- {
- _leftEventManager.OnComboChanged.Invoke(combo);
- _rightEventManager.OnComboChanged.Invoke(combo);
- }
- }
-}
\ No newline at end of file
diff --git a/CustomSaber/Settings/Configuration.cs b/CustomSaber/Settings/Configuration.cs
new file mode 100644
index 0000000..2ac364b
--- /dev/null
+++ b/CustomSaber/Settings/Configuration.cs
@@ -0,0 +1,52 @@
+using CustomSaber.Settings.Utilities;
+using CustomSaber.Utilities;
+using IPA.Config;
+using IPA.Config.Stores;
+using System;
+
+namespace CustomSaber.Settings
+{
+ public class Configuration
+ {
+ public static string CurrentlySelectedSaber { get; internal set; }
+ public static TrailType TrailType { get; internal set; }
+ public static bool CustomEventsEnabled { get; internal set; }
+ public static bool RandomSabersEnabled { get; internal set; }
+ public static bool ShowSabersInSaberMenu { get; internal set; }
+ public static bool OverrideTrailLength { get; internal set; }
+ public static float TrailLength { get; internal set; }
+ public static float SaberWidthAdjust { get; internal set; }
+ public static bool DisableWhitestep { get; internal set; }
+
+ internal static void Init(Config config)
+ {
+ PluginConfig.Instance = config.Generated();
+ }
+
+ internal static void Load()
+ {
+ CurrentlySelectedSaber = PluginConfig.Instance.lastSaber;
+ TrailType = Enum.TryParse(PluginConfig.Instance.trailType, out TrailType trailType) ? trailType : TrailType.Custom;
+ CustomEventsEnabled = PluginConfig.Instance.customEventsEnabled;
+ RandomSabersEnabled = PluginConfig.Instance.randomSabersEnabled;
+ ShowSabersInSaberMenu = PluginConfig.Instance.showSabersInSaberMenu;
+ OverrideTrailLength = PluginConfig.Instance.overrideCustomTrailLength;
+ TrailLength = PluginConfig.Instance.trailLength;
+ SaberWidthAdjust = PluginConfig.Instance.saberWidthAdjust;
+ DisableWhitestep = PluginConfig.Instance.disableWhitestep;
+ }
+
+ internal static void Save()
+ {
+ PluginConfig.Instance.lastSaber = CurrentlySelectedSaber;
+ PluginConfig.Instance.trailType = TrailType.ToString();
+ PluginConfig.Instance.customEventsEnabled = CustomEventsEnabled;
+ PluginConfig.Instance.randomSabersEnabled = RandomSabersEnabled;
+ PluginConfig.Instance.showSabersInSaberMenu = ShowSabersInSaberMenu;
+ PluginConfig.Instance.overrideCustomTrailLength = OverrideTrailLength;
+ PluginConfig.Instance.trailLength = TrailLength;
+ PluginConfig.Instance.saberWidthAdjust = SaberWidthAdjust;
+ PluginConfig.Instance.disableWhitestep = DisableWhitestep;
+ }
+ }
+}
diff --git a/CustomSaber/Settings/UI/SaberListViewController.cs b/CustomSaber/Settings/UI/SaberListViewController.cs
new file mode 100644
index 0000000..19ec7b6
--- /dev/null
+++ b/CustomSaber/Settings/UI/SaberListViewController.cs
@@ -0,0 +1,327 @@
+using BeatSaberMarkupLanguage.Attributes;
+using BeatSaberMarkupLanguage.Components;
+using BeatSaberMarkupLanguage.ViewControllers;
+using CustomSaber.Data;
+using CustomSaber.Utilities;
+using HMUI;
+using IPA.Utilities;
+using System;
+using System.Collections;
+using System.Linq;
+using TMPro;
+using UnityEngine;
+using UnityEngine.XR;
+
+namespace CustomSaber.Settings.UI
+{
+ internal class SaberListViewController : BSMLResourceViewController
+ {
+ public override string ResourceName => "CustomSaber.Settings.UI.Views.saberList.bsml";
+
+ public static SaberListViewController Instance;
+
+ private bool isGeneratingPreview;
+ private GameObject preview;
+
+ // Sabers
+ private GameObject previewSabers;
+ private GameObject leftSaber;
+ private GameObject rightSaber;
+
+ // SaberPositions (Local to the previewer)
+ private Vector3 sabersPos = new Vector3(0, 0, 0);
+ private Vector3 saberLeftPos = new Vector3(0, 0, 0);
+ private Vector3 saberRightPos = new Vector3(0, 0.5f, 0);
+
+ public Action customSaberChanged;
+
+ [UIComponent("saberList")]
+ public CustomListTableData customListTableData;
+
+ [UIAction("saberSelect")]
+ public void Select(TableView _, int row)
+ {
+ SaberAssetLoader.SelectedSaber = row;
+ Configuration.CurrentlySelectedSaber = SaberAssetLoader.CustomSabers[row].FileName;
+ customSaberChanged?.Invoke(SaberAssetLoader.CustomSabers[row]);
+
+ StartCoroutine(GenerateSaberPreview(row));
+ }
+
+ [UIAction("reloadSabers")]
+ public void ReloadMaterials()
+ {
+ SaberAssetLoader.Reload();
+ SetupList();
+ Select(customListTableData.tableView, SaberAssetLoader.SelectedSaber);
+ }
+
+ [UIAction("deleteSaber")]
+ public void DeleteCurrentSaber()
+ {
+ var deletedSaber = SaberAssetLoader.DeleteCurrentSaber();
+
+ if (deletedSaber == 0) return;
+
+ SetupList();
+ Select(customListTableData.tableView, SaberAssetLoader.SelectedSaber);
+ }
+
+ [UIAction("update-confirmation")]
+ public void UpdateDeleteConfirmation() => confirmationText.text = $"Are you sure you want to delete\n{SaberAssetLoader.CustomSabers[SaberAssetLoader.SelectedSaber].Descriptor.SaberName}?";
+
+ [UIComponent("delete-saber-confirmation-text")]
+ public TextMeshProUGUI confirmationText;
+
+ [UIAction("#post-parse")]
+ public void SetupList()
+ {
+ customListTableData.data.Clear();
+ foreach (var saber in SaberAssetLoader.CustomSabers)
+ {
+ var customCellInfo = new CustomListTableData.CustomCellInfo(saber.Descriptor.SaberName, saber.Descriptor.AuthorName, saber.Descriptor.CoverImage?.texture);
+ customListTableData.data.Add(customCellInfo);
+ }
+
+ customListTableData.tableView.ReloadData();
+ var selectedSaber = SaberAssetLoader.SelectedSaber;
+
+ customListTableData.tableView.SelectCellWithIdx(selectedSaber);
+ if (!customListTableData.tableView.visibleCells.Where(x => x.selected).Any())
+ customListTableData.tableView.ScrollToCellWithIdx(selectedSaber, TableViewScroller.ScrollPositionType.Beginning, true);
+ }
+
+ protected override void DidActivate(bool firstActivation, ActivationType type)
+ {
+ base.DidActivate(firstActivation, type);
+
+ Instance = this;
+
+ if (!preview)
+ {
+ preview = new GameObject("Preview");
+ preview.transform.position = new Vector3(2.2f, 1.3f, 1.0f);
+ preview.transform.Rotate(0.0f, 330.0f, 0.0f);
+ }
+
+ Select(customListTableData.tableView, SaberAssetLoader.SelectedSaber);
+ }
+
+ protected override void DidDeactivate(DeactivationType deactivationType)
+ {
+ base.DidDeactivate(deactivationType);
+ ClearPreview();
+ }
+
+ public IEnumerator GenerateSaberPreview(int selectedSaber)
+ {
+ if (!isGeneratingPreview)
+ {
+ yield return new WaitUntil(() => DefaultSaberGrabber.isCompleted);
+ try
+ {
+ isGeneratingPreview = true;
+ ClearSabers();
+
+ var customSaber = SaberAssetLoader.CustomSabers[selectedSaber];
+ if (customSaber != null)
+ {
+
+ previewSabers = CreatePreviewSaber(customSaber.Sabers, preview.transform, sabersPos);
+ PositionPreviewSaber(saberLeftPos, previewSabers?.transform.Find("LeftSaber").gameObject);
+ PositionPreviewSaber(saberRightPos, previewSabers?.transform.Find("RightSaber").gameObject);
+
+ previewSabers?.transform.Find("LeftSaber").gameObject.SetActive(true);
+ previewSabers?.transform.Find("LeftSaber").gameObject.gameObject.AddComponent();
+ previewSabers?.transform.Find("RightSaber").gameObject.SetActive(true);
+ previewSabers?.transform.Find("RightSaber").gameObject.gameObject.AddComponent();
+
+ if (Configuration.ShowSabersInSaberMenu)
+ GenerateHandheldSaberPreview();
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.log.Error(ex);
+ }
+ finally
+ {
+ isGeneratingPreview = false;
+ }
+ }
+ }
+
+ private GameObject CreatePreviewSaber(GameObject saber, Transform transform, Vector3 localPosition)
+ {
+ if (!saber) return null;
+ var saberObject = InstantiateGameObject(saber, transform);
+ saberObject.name = "Preview Saber Object";
+ PositionPreviewSaber(localPosition, saberObject);
+ return saberObject;
+ }
+
+ public void GenerateHandheldSaberPreview()
+ {
+ if (Environment.CommandLine.Contains("fpfc")) return;
+ var customSaber = SaberAssetLoader.CustomSabers[SaberAssetLoader.SelectedSaber];
+ if (customSaber == null || !customSaber.Sabers) return;
+ var controllers = Resources.FindObjectsOfTypeAll();
+ var sabers = CreatePreviewSaber(customSaber.Sabers, preview.transform, sabersPos);
+ var colorManager = Resources.FindObjectsOfTypeAll().First();
+
+ try
+ {
+ foreach (var controller in controllers)
+ {
+ if (controller?.node == XRNode.LeftHand)
+ {
+ leftSaber = sabers?.transform.Find("LeftSaber").gameObject;
+ if (!leftSaber) continue;
+
+ leftSaber.transform.parent = controller.transform;
+ leftSaber.transform.position = controller.transform.position;
+ leftSaber.transform.rotation = controller.transform.rotation;
+
+ leftSaber.SetActive(true);
+
+ var trails = leftSaber.GetComponentsInChildren();
+
+ if (trails == null || trails.Count() == 0)
+ {
+ var defaultTrail = Instantiate(DefaultSaberGrabber.defaultLeftSaber, leftSaber.transform);
+ defaultTrail.SetActive(true);
+ defaultTrail.transform.localPosition = Vector3.zero;
+ defaultTrail.transform.localRotation = Quaternion.identity;
+ defaultTrail.transform.Find("BasicSaber").gameObject.SetActive(false);
+ }
+ else
+ {
+ foreach (var trail in trails)
+ {
+ trail.Length = (Configuration.OverrideTrailLength) ? (int) (trail.Length * Configuration.TrailLength) : trail.Length;
+ if (trail.Length < 2 || !trail.PointStart || !trail.PointEnd) continue;
+ leftSaber.AddComponent().Init(ReflectionUtil.GetField(DefaultSaberGrabber.trail, "_trailRendererPrefab"),
+ colorManager, trail.PointStart, trail.PointEnd, trail.TrailMaterial, trail.TrailColor, trail.Length, trail.Granularity, trail.MultiplierColor, trail.colorType);
+ }
+ }
+
+ leftSaber.AddComponent();
+
+ controller.transform.Find("MenuHandle")?.gameObject.SetActive(false);
+ }
+ else if (controller?.node == XRNode.RightHand)
+ {
+ rightSaber = sabers?.transform.Find("RightSaber").gameObject;
+ if (!rightSaber) continue;
+
+ rightSaber.transform.parent = controller.transform;
+ rightSaber.transform.position = controller.transform.position;
+ rightSaber.transform.rotation = controller.transform.rotation;
+
+ rightSaber.SetActive(true);
+
+ var trails = rightSaber.GetComponentsInChildren();
+
+ if (trails == null || trails.Count() == 0)
+ {
+ var defaultTrail = Instantiate(DefaultSaberGrabber.defaultRightSaber, rightSaber.transform);
+ defaultTrail.SetActive(true);
+ defaultTrail.transform.localPosition = Vector3.zero;
+ defaultTrail.transform.localRotation = Quaternion.identity;
+ defaultTrail.transform.Find("BasicSaber").gameObject.SetActive(false);
+ }
+ else
+ {
+ foreach (var trail in trails)
+ {
+ trail.Length = (Configuration.OverrideTrailLength) ? (int)(trail.Length * Configuration.TrailLength) : trail.Length;
+ if (trail.Length < 2 || !trail.PointStart || !trail.PointEnd) continue;
+ rightSaber.AddComponent().Init(ReflectionUtil.GetField(DefaultSaberGrabber.trail, "_trailRendererPrefab"),
+ colorManager, trail.PointStart, trail.PointEnd, trail.TrailMaterial, trail.TrailColor, trail.Length, trail.Granularity, trail.MultiplierColor, trail.colorType);
+ }
+ }
+
+ rightSaber.AddComponent();
+
+ controller.transform.Find("MenuHandle")?.gameObject.SetActive(false);
+ }
+ if (leftSaber && rightSaber) break;
+ }
+ StartCoroutine(HideOrShowPointer());
+ }
+ catch(Exception e)
+ {
+ Logger.log.Error($"Error generating saber preview\n{e.Message} - {e.StackTrace}");
+ }
+ finally
+ {
+ DestroyGameObject(ref sabers);
+ }
+ }
+
+ private GameObject InstantiateGameObject(GameObject gameObject, Transform transform = null)
+ {
+ if (gameObject)
+ {
+ return transform ? Instantiate(gameObject, transform) : Instantiate(gameObject);
+ }
+
+ return null;
+ }
+
+ private void PositionPreviewSaber(Vector3 vector, GameObject saberObject)
+ {
+ if (saberObject && vector != null)
+ {
+ saberObject.transform.localPosition = vector;
+ }
+ }
+
+ private void ClearPreview()
+ {
+ ClearSabers();
+ DestroyGameObject(ref preview);
+ ShowMenuHandles();
+ }
+
+ private void ClearSabers()
+ {
+ DestroyGameObject(ref previewSabers);
+ ClearHandheldSabers();
+ }
+
+ public void ClearHandheldSabers()
+ {
+ DestroyGameObject(ref leftSaber);
+ DestroyGameObject(ref rightSaber);
+ }
+
+ float initialSize = -1;
+ VRUIControls.VRPointer pointer = null;
+ IEnumerator HideOrShowPointer(bool enable = false)
+ {
+ yield return new WaitUntil(() => pointer = Resources.FindObjectsOfTypeAll().FirstOrDefault());
+ if (initialSize == -1) initialSize = ReflectionUtil.GetField(pointer, "_laserPointerWidth");
+ pointer.SetField("_laserPointerWidth", enable ? initialSize : 0f);
+ }
+
+ public void ShowMenuHandles()
+ {
+ foreach (var controller in Resources.FindObjectsOfTypeAll())
+ {
+ controller.transform?.Find("MenuHandle")?.gameObject?.SetActive(true);
+ }
+
+ StartCoroutine(HideOrShowPointer(true));
+ }
+
+ private void DestroyGameObject(ref GameObject gameObject)
+ {
+ if (gameObject)
+ {
+ DestroyImmediate(gameObject);
+ gameObject = null;
+ }
+ }
+ }
+}
diff --git a/CustomSaber/Settings/UI/SaberPreviewViewController.cs b/CustomSaber/Settings/UI/SaberPreviewViewController.cs
new file mode 100644
index 0000000..2045cd5
--- /dev/null
+++ b/CustomSaber/Settings/UI/SaberPreviewViewController.cs
@@ -0,0 +1,29 @@
+using BeatSaberMarkupLanguage.Attributes;
+using BeatSaberMarkupLanguage.ViewControllers;
+using CustomSaber.Data;
+using CustomSaber.Utilities;
+using HMUI;
+
+namespace CustomSaber.Settings.UI
+{
+ internal class SaberPreviewViewController : BSMLResourceViewController
+ {
+ public override string ResourceName => "CustomSaber.Settings.UI.Views.saberPreview.bsml";
+
+ [UIComponent("error-description")]
+ public TextPageScrollView errorDescription;
+
+ public void OnSaberWasChanged(CustomSaberData customSaber)
+ {
+ if (!string.IsNullOrWhiteSpace(customSaber?.ErrorMessage))
+ {
+ errorDescription.gameObject.SetActive(true);
+ errorDescription.SetText($"{customSaber.Descriptor?.SaberName}:\n\n{Utils.SafeUnescape(customSaber.ErrorMessage)}");
+ }
+ else
+ {
+ errorDescription.gameObject.SetActive(false);
+ }
+ }
+ }
+}
diff --git a/CustomSaber/Settings/UI/SaberSettingsViewController.cs b/CustomSaber/Settings/UI/SaberSettingsViewController.cs
new file mode 100644
index 0000000..3d4a8eb
--- /dev/null
+++ b/CustomSaber/Settings/UI/SaberSettingsViewController.cs
@@ -0,0 +1,96 @@
+using BeatSaberMarkupLanguage.Attributes;
+using BeatSaberMarkupLanguage.ViewControllers;
+using CustomSaber.Utilities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CustomSaber.Settings.UI
+{
+ internal class SaberSettingsViewController : BSMLResourceViewController
+ {
+ public override string ResourceName => "CustomSaber.Settings.UI.Views.saberSettings.bsml";
+
+ [UIValue("trail-type")]
+ public string TrailType
+ {
+ get => Configuration.TrailType.ToString();
+ set => Configuration.TrailType = Enum.TryParse(value, out TrailType trailType) ? trailType : Configuration.TrailType;
+ }
+
+ [UIValue("trail-type-list")]
+ public List