├── Deformers
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── Deformers.csproj
└── Deformers.cs
├── nuget.config
├── Deformers.sln
├── README.md
├── .gitattributes
└── .gitignore
/Deformers/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Deformers.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30523.141
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Deformers", "Deformers\Deformers.csproj", "{49FB735D-DF67-44B7-8790-59E1B3C0AB5D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {49FB735D-DF67-44B7-8790-59E1B3C0AB5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {49FB735D-DF67-44B7-8790-59E1B3C0AB5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {49FB735D-DF67-44B7-8790-59E1B3C0AB5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {49FB735D-DF67-44B7-8790-59E1B3C0AB5D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B2B201CF-2F43-4055-B8C2-3E3B2EC30791}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Illusion_Deformers
2 |
3 | HS2 for now.
4 | Copy the .dll to BepInEx\Plugins and the .zipmod to (my)mods.
5 |
6 | "Squeezer", "Bulger", "Mover", "Rotator" accessories in the "Arms" category.
7 |
8 | - "Adjustment 01" is the selector: move around and scale to set the area that should be deformed. There's a sphere/capsule attached to give you an idea which area is being deformed. You can turn it completely transparent with the color option once it's in place.
9 | - "Adjustment 02" is for adjusting the deformation: Position changes the offset, Scale X is the strength, Scale Y is the falloff. The values aren't restricted so you can make glitchy eldritch monsters, but in general you probably want low values here, under 2. With the capsule variants, scale Z controls how much the deformation is based on the center of the capsule (z=1) vs the axis of the capsule (z=0).
10 | - You can add multiple deformers, order is top to bottom. Each deformer uses the result of the previous deformers as the base.
11 | - Switch the accessory's "Filter"-Material shader from "Standard" to something else to only deform renderers with that shader (with Material Editor). Switch to "Clothes True" to only deform clothes and not skin for example. Also helps with performance.
12 | - Deformers can be accessed, adjusted and used for animations in studio with HSPE. Just search for "move" bones.
13 |
14 | Quick demo:
15 | https://streamable.com/ed2qkz
16 |
--------------------------------------------------------------------------------
/Deformers/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Deformers")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Deformers")]
13 | [assembly: AssemblyCopyright("Copyright © 2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("49fb735d-df67-44b7-8790-59e1b3c0ab5d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/Deformers/Deformers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {49FB735D-DF67-44B7-8790-59E1B3C0AB5D}
8 | Library
9 | Properties
10 | Deformers
11 | Deformers
12 | v4.6
13 | 512
14 | true
15 |
16 |
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 | true
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | true
36 |
37 |
38 |
39 | ..\Libs\0Harmony.dll
40 |
41 |
42 | ..\Libs\Assembly-CSharp.dll
43 |
44 |
45 | ..\Libs\Assembly-CSharp-firstpass.dll
46 |
47 |
48 | ..\Libs\BepInEx.dll
49 |
50 |
51 | ..\Libs\BepInEx.Harmony.dll
52 |
53 |
54 | ..\Libs\HS2API.dll
55 |
56 |
57 | ..\Libs\HS2_ExtensibleSaveFormat.dll
58 |
59 |
60 |
61 |
62 | ..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | ..\Libs\Unity.Burst.dll
72 |
73 |
74 | ..\Libs\Unity.Mathematics.dll
75 |
76 |
77 | ..\Libs\UnityEngine.dll
78 |
79 |
80 | ..\Libs\UnityEngine.AnimationModule.dll
81 |
82 |
83 | ..\Libs\UnityEngine.ClothModule.dll
84 |
85 |
86 | ..\Libs\UnityEngine.CoreModule.dll
87 |
88 |
89 | ..\Libs\UnityEngine.PhysicsModule.dll
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 | /Libs
13 |
14 | # User-specific files (MonoDevelop/Xamarin Studio)
15 | *.userprefs
16 |
17 | # Build results
18 | [Dd]ebug/
19 | [Dd]ebugPublic/
20 | [Rr]elease/
21 | [Rr]eleases/
22 | x64/
23 | x86/
24 | [Aa][Rr][Mm]/
25 | [Aa][Rr][Mm]64/
26 | bld/
27 | [Bb]in/
28 | [Oo]bj/
29 | [Ll]og/
30 |
31 | # Visual Studio 2015/2017 cache/options directory
32 | .vs/
33 | # Uncomment if you have tasks that create the project's static files in wwwroot
34 | #wwwroot/
35 |
36 | # Visual Studio 2017 auto generated files
37 | Generated\ Files/
38 |
39 | # MSTest test Results
40 | [Tt]est[Rr]esult*/
41 | [Bb]uild[Ll]og.*
42 |
43 | # NUNIT
44 | *.VisualState.xml
45 | TestResult.xml
46 |
47 | # Build Results of an ATL Project
48 | [Dd]ebugPS/
49 | [Rr]eleasePS/
50 | dlldata.c
51 |
52 | # Benchmark Results
53 | BenchmarkDotNet.Artifacts/
54 |
55 | # .NET Core
56 | project.lock.json
57 | project.fragment.lock.json
58 | artifacts/
59 |
60 | # StyleCop
61 | StyleCopReport.xml
62 |
63 | # Files built by Visual Studio
64 | *_i.c
65 | *_p.c
66 | *_h.h
67 | *.ilk
68 | *.meta
69 | *.obj
70 | *.iobj
71 | *.pch
72 | *.pdb
73 | *.ipdb
74 | *.pgc
75 | *.pgd
76 | *.rsp
77 | *.sbr
78 | *.tlb
79 | *.tli
80 | *.tlh
81 | *.tmp
82 | *.tmp_proj
83 | *_wpftmp.csproj
84 | *.log
85 | *.vspscc
86 | *.vssscc
87 | .builds
88 | *.pidb
89 | *.svclog
90 | *.scc
91 |
92 | # Chutzpah Test files
93 | _Chutzpah*
94 |
95 | # Visual C++ cache files
96 | ipch/
97 | *.aps
98 | *.ncb
99 | *.opendb
100 | *.opensdf
101 | *.sdf
102 | *.cachefile
103 | *.VC.db
104 | *.VC.VC.opendb
105 |
106 | # Visual Studio profiler
107 | *.psess
108 | *.vsp
109 | *.vspx
110 | *.sap
111 |
112 | # Visual Studio Trace Files
113 | *.e2e
114 |
115 | # TFS 2012 Local Workspace
116 | $tf/
117 |
118 | # Guidance Automation Toolkit
119 | *.gpState
120 |
121 | # ReSharper is a .NET coding add-in
122 | _ReSharper*/
123 | *.[Rr]e[Ss]harper
124 | *.DotSettings.user
125 |
126 | # JustCode is a .NET coding add-in
127 | .JustCode
128 |
129 | # TeamCity is a build add-in
130 | _TeamCity*
131 |
132 | # DotCover is a Code Coverage Tool
133 | *.dotCover
134 |
135 | # AxoCover is a Code Coverage Tool
136 | .axoCover/*
137 | !.axoCover/settings.json
138 |
139 | # Visual Studio code coverage results
140 | *.coverage
141 | *.coveragexml
142 |
143 | # NCrunch
144 | _NCrunch_*
145 | .*crunch*.local.xml
146 | nCrunchTemp_*
147 |
148 | # MightyMoose
149 | *.mm.*
150 | AutoTest.Net/
151 |
152 | # Web workbench (sass)
153 | .sass-cache/
154 |
155 | # Installshield output folder
156 | [Ee]xpress/
157 |
158 | # DocProject is a documentation generator add-in
159 | DocProject/buildhelp/
160 | DocProject/Help/*.HxT
161 | DocProject/Help/*.HxC
162 | DocProject/Help/*.hhc
163 | DocProject/Help/*.hhk
164 | DocProject/Help/*.hhp
165 | DocProject/Help/Html2
166 | DocProject/Help/html
167 |
168 | # Click-Once directory
169 | publish/
170 |
171 | # Publish Web Output
172 | *.[Pp]ublish.xml
173 | *.azurePubxml
174 | # Note: Comment the next line if you want to checkin your web deploy settings,
175 | # but database connection strings (with potential passwords) will be unencrypted
176 | *.pubxml
177 | *.publishproj
178 |
179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
180 | # checkin your Azure Web App publish settings, but sensitive information contained
181 | # in these scripts will be unencrypted
182 | PublishScripts/
183 |
184 | # NuGet Packages
185 | *.nupkg
186 | # The packages folder can be ignored because of Package Restore
187 | **/[Pp]ackages/*
188 | # except build/, which is used as an MSBuild target.
189 | !**/[Pp]ackages/build/
190 | # Uncomment if necessary however generally it will be regenerated when needed
191 | #!**/[Pp]ackages/repositories.config
192 | # NuGet v3's project.json files produces more ignorable files
193 | *.nuget.props
194 | *.nuget.targets
195 |
196 | # Microsoft Azure Build Output
197 | csx/
198 | *.build.csdef
199 |
200 | # Microsoft Azure Emulator
201 | ecf/
202 | rcf/
203 |
204 | # Windows Store app package directories and files
205 | AppPackages/
206 | BundleArtifacts/
207 | Package.StoreAssociation.xml
208 | _pkginfo.txt
209 | *.appx
210 |
211 | # Visual Studio cache files
212 | # files ending in .cache can be ignored
213 | *.[Cc]ache
214 | # but keep track of directories ending in .cache
215 | !?*.[Cc]ache/
216 |
217 | # Others
218 | ClientBin/
219 | ~$*
220 | *~
221 | *.dbmdl
222 | *.dbproj.schemaview
223 | *.jfm
224 | *.pfx
225 | *.publishsettings
226 | orleans.codegen.cs
227 |
228 | # Including strong name files can present a security risk
229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
230 | #*.snk
231 |
232 | # Since there are multiple workflows, uncomment next line to ignore bower_components
233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
234 | #bower_components/
235 |
236 | # RIA/Silverlight projects
237 | Generated_Code/
238 |
239 | # Backup & report files from converting an old project file
240 | # to a newer Visual Studio version. Backup files are not needed,
241 | # because we have git ;-)
242 | _UpgradeReport_Files/
243 | Backup*/
244 | UpgradeLog*.XML
245 | UpgradeLog*.htm
246 | ServiceFabricBackup/
247 | *.rptproj.bak
248 |
249 | # SQL Server files
250 | *.mdf
251 | *.ldf
252 | *.ndf
253 |
254 | # Business Intelligence projects
255 | *.rdl.data
256 | *.bim.layout
257 | *.bim_*.settings
258 | *.rptproj.rsuser
259 | *- Backup*.rdl
260 |
261 | # Microsoft Fakes
262 | FakesAssemblies/
263 |
264 | # GhostDoc plugin setting file
265 | *.GhostDoc.xml
266 |
267 | # Node.js Tools for Visual Studio
268 | .ntvs_analysis.dat
269 | node_modules/
270 |
271 | # Visual Studio 6 build log
272 | *.plg
273 |
274 | # Visual Studio 6 workspace options file
275 | *.opt
276 |
277 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
278 | *.vbw
279 |
280 | # Visual Studio LightSwitch build output
281 | **/*.HTMLClient/GeneratedArtifacts
282 | **/*.DesktopClient/GeneratedArtifacts
283 | **/*.DesktopClient/ModelManifest.xml
284 | **/*.Server/GeneratedArtifacts
285 | **/*.Server/ModelManifest.xml
286 | _Pvt_Extensions
287 |
288 | # Paket dependency manager
289 | .paket/paket.exe
290 | paket-files/
291 |
292 | # FAKE - F# Make
293 | .fake/
294 |
295 | # JetBrains Rider
296 | .idea/
297 | *.sln.iml
298 |
299 | # CodeRush personal settings
300 | .cr/personal
301 |
302 | # Python Tools for Visual Studio (PTVS)
303 | __pycache__/
304 | *.pyc
305 |
306 | # Cake - Uncomment if you are using it
307 | # tools/**
308 | # !tools/packages.config
309 |
310 | # Tabs Studio
311 | *.tss
312 |
313 | # Telerik's JustMock configuration file
314 | *.jmconfig
315 |
316 | # BizTalk build output
317 | *.btp.cs
318 | *.btm.cs
319 | *.odx.cs
320 | *.xsd.cs
321 |
322 | # OpenCover UI analysis results
323 | OpenCover/
324 |
325 | # Azure Stream Analytics local run output
326 | ASALocalRun/
327 |
328 | # MSBuild Binary and Structured Log
329 | *.binlog
330 |
331 | # NVidia Nsight GPU debugger configuration file
332 | *.nvuser
333 |
334 | # MFractors (Xamarin productivity tool) working folder
335 | .mfractor/
336 |
337 | # Local History for Visual Studio
338 | .localhistory/
339 |
340 | # BeatPulse healthcheck temp database
341 | healthchecksdb
--------------------------------------------------------------------------------
/Deformers/Deformers.cs:
--------------------------------------------------------------------------------
1 | using AIChara;
2 | using BepInEx;
3 | using BepInEx.Logging;
4 | using ExtensibleSaveFormat;
5 | using HarmonyLib;
6 | using KKAPI;
7 | using KKAPI.Chara;
8 | using KKAPI.Maker;
9 | using MessagePack;
10 | using System;
11 | using System.Collections;
12 | using System.Collections.Generic;
13 | using System.Reflection;
14 | using UnityEngine;
15 | using Unity.Jobs;
16 | using UnityEngine.Jobs;
17 | using Unity.Collections;
18 | using Unity.Burst;
19 |
20 | [BepInDependency(KoikatuAPI.GUID, KoikatuAPI.VersionConst)]
21 | [BepInPlugin(GUID, "Deformers", Version)]
22 | public class Deformers : BaseUnityPlugin
23 | {
24 | public const string GUID = "dainty.deformers";
25 | public const string Version = "0.6";
26 | internal static new ManualLogSource Logger;
27 | void Awake()
28 | {
29 | Logger = base.Logger;
30 | CharacterApi.RegisterExtraBehaviour(GUID);
31 | Harmony.CreateAndPatchAll(typeof(Hooks));
32 | AccessoriesApi.AccessoryTransferred += AccCopy; //copying destroys clothing renderer references, somehow
33 | }
34 | void AccCopy(object sender, AccessoryTransferEventArgs e)
35 | {
36 | ChaControl chaCtrl = MakerAPI.GetCharacterControl();
37 | DeformersController deformersController = chaCtrl.GetComponent();
38 | chaCtrl.StartCoroutine(deformersController.GetAllRenderers(false, true));
39 | }
40 |
41 | class Hooks
42 | {
43 | [HarmonyPostfix]
44 | [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.ChangeClothes), new Type[] { typeof(int), typeof(int), typeof(bool) })]
45 | private static void ChangeClothesHook(ChaControl __instance, int kind, int id)
46 | {
47 | DeformersController deformersController = __instance.GetComponent();
48 | __instance.StartCoroutine(deformersController.GetAllRenderers());
49 | }
50 |
51 | [HarmonyPostfix]
52 | [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.ChangeHair), new Type[] { typeof(int), typeof(int), typeof(bool) })]
53 | private static void ChangeHairHook(ChaControl __instance, int kind, int id)
54 | {
55 | DeformersController deformersController = __instance.GetComponent();
56 | __instance.StartCoroutine(deformersController.GetAllRenderers());
57 | }
58 |
59 | [HarmonyPostfix]
60 | [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.ChangeHead), new Type[] { typeof(int), typeof(bool) })]
61 | private static void ChangeHeadHook(ChaControl __instance, int _headId, bool forceChange)
62 | {
63 | DeformersController deformersController = __instance.GetComponent();
64 | __instance.StartCoroutine(deformersController.GetAllRenderers());
65 | }
66 | [HarmonyPostfix]
67 | [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.ChangeAccessory), new Type[] { typeof(int), typeof(int), typeof(int), typeof(string), typeof(bool) })]
68 | private static void ChangeAccessoryHook(ChaControl __instance, int slotNo, int type, int id, string parentKey, bool forceChange)
69 | {
70 | DeformersController deformersController = __instance.GetComponent();
71 | __instance.StartCoroutine(deformersController.GetAllRenderers());
72 | }
73 | }
74 | }
75 |
76 |
77 |
78 | public class DeformersController : CharaCustomFunctionController
79 | {
80 | public Component[] Renderers { get; private set; }
81 | public Dictionary OrigMeshes { get; private set; }
82 | public List DeformerList { get; set; }
83 | List origVertices = new List();
84 | List newVertices = new List();
85 | List bakedVertices = new List();
86 | Mesh bakedMesh = new Mesh();
87 | private bool loaded = false;
88 | private float loadedTime = 0f;
89 | private List normals = new List();
90 | private List newNormals = new List();
91 | public Dictionary NormalDiffs { get; set; }
92 |
93 | public Dictionary DuplicateVectors { get; set; }
94 | public Dictionary> ResultList = new Dictionary>();
95 |
96 | private string GetPartialHierarchyPath(Transform transform)
97 | {
98 | string path = transform.name;
99 | while (true)
100 | {
101 | if (transform.parent == null || transform.parent == this.transform)
102 | {
103 | break;
104 | }
105 | transform = transform.parent;
106 | path = transform.name + "/" + path;
107 | }
108 | return path;
109 | }
110 | protected override void OnCardBeingSaved(GameMode currentGameMode)
111 | {
112 | PluginData deformData = new PluginData();
113 |
114 | foreach (Component renderer in Renderers)
115 | {
116 | if (renderer == null)
117 | {
118 | continue;
119 | }
120 | Mesh sharedMesh = GetMesh(renderer);
121 | if (sharedMesh == null)
122 | {
123 | continue;
124 | }
125 | if (!OrigMeshes.ContainsKey(sharedMesh))
126 | {
127 | continue;
128 | }
129 | if (!sharedMesh.isReadable)
130 | {
131 | continue;
132 | }
133 | List savedVertices = new List();
134 | sharedMesh.GetVertices(newVertices);
135 | OrigMeshes[sharedMesh].GetVertices(origVertices);
136 | for (var j = 0; j < newVertices.Count; j++)
137 | {
138 | if (newVertices[j] != origVertices[j])
139 | {
140 | savedVertices.Add(new float[] { j, newVertices[j].x, newVertices[j].y, newVertices[j].z });
141 | }
142 | }
143 |
144 | if (savedVertices.Count > 0)
145 | {
146 | if (deformData.data.ContainsKey(GetPartialHierarchyPath(renderer.transform) + newVertices.Count))
147 | {
148 | continue;
149 | }
150 | deformData.data.Add(GetPartialHierarchyPath(renderer.transform) + newVertices.Count, MessagePackSerializer.Serialize(savedVertices, MessagePack.Resolvers.ContractlessStandardResolver.Instance));
151 | }
152 | }
153 | deformData.version = 1;
154 | if (deformData.data.Count > 0)
155 | {
156 | SetExtendedData(deformData);
157 | }
158 | else
159 | {
160 | SetExtendedData(null);
161 | }
162 | }
163 |
164 | protected override void OnReload(GameMode currentGameMode, bool maintainState)
165 | {
166 | OrigMeshes = new Dictionary();
167 | NormalDiffs = new Dictionary();
168 | DuplicateVectors = new Dictionary();
169 | loaded = false;
170 | StartCoroutine(GetAllRenderers(true));
171 | }
172 |
173 | protected override void OnCoordinateBeingLoaded(ChaFileCoordinate coordinate)
174 | {
175 | StartCoroutine(GetAllRenderers(false, true));
176 | }
177 |
178 | public Mesh GetMesh(Component renderer)
179 | {
180 | if (renderer is SkinnedMeshRenderer skinnedMeshRenderer)
181 | {
182 | return skinnedMeshRenderer.sharedMesh;
183 | }
184 | if (renderer is MeshRenderer meshRenderer)
185 | {
186 | if (meshRenderer.material.name.StartsWith("Filter")) //dumb way of not deforming deformers
187 | {
188 | return null;
189 | }
190 | return meshRenderer.GetComponent().sharedMesh;
191 | }
192 | return null;
193 | }
194 |
195 | public void SetMesh(Component renderer, Mesh mesh)
196 | {
197 | if (renderer is SkinnedMeshRenderer skinnedMeshRenderer)
198 | {
199 | skinnedMeshRenderer.sharedMesh = mesh;
200 | if (skinnedMeshRenderer.gameObject.GetComponent() != null)
201 | {
202 | CopyCloth(skinnedMeshRenderer.gameObject);
203 | }
204 | }
205 | if (renderer is MeshRenderer meshRenderer)
206 | {
207 | meshRenderer.GetComponent().sharedMesh = mesh;
208 | }
209 | }
210 | public static void CopyCloth(GameObject renderer) //cloth component bugs out if you replace the mesh and then disable and enable the gameobject
211 | {
212 | GameObject copy = Instantiate(renderer);
213 | Cloth clothCopy = copy.GetComponent();
214 |
215 | DestroyImmediate(renderer.GetComponent());
216 | Cloth clothOrig = renderer.AddComponent();
217 |
218 | string name = renderer.name;
219 |
220 | Transform ancestor = clothOrig.transform;
221 | while (ancestor.parent != null)
222 | {
223 | ancestor = ancestor.parent;
224 | ancestor.gameObject.SetActive(true);
225 | if (clothOrig.gameObject.activeInHierarchy == true)
226 | {
227 | break;
228 | }
229 | }
230 | foreach (PropertyInfo x in typeof(Cloth).GetProperties())
231 | {
232 | if (x.CanWrite)
233 | x.SetValue(clothOrig, x.GetValue(clothCopy));
234 | }
235 | clothOrig.clothSolverFrequency = clothCopy.clothSolverFrequency;
236 | renderer.name = name;
237 |
238 | copy.SetActive(false);
239 | Destroy(copy);
240 | }
241 |
242 | public IEnumerator GetAllRenderers(bool reload = false, bool deform = false)
243 | {
244 | yield return new WaitForSeconds(0.5f); //renderers/meshes get replaced by plugins at some point, I tried hooking the load manually and setting priority to last, doesn't work. Something async I guess.
245 |
246 | Renderers = transform.GetComponentsInChildren(typeof(Renderer), true);
247 | foreach (Component renderer in Renderers)
248 | {
249 | Mesh sharedMesh = GetMesh(renderer);
250 | if (sharedMesh == null)
251 | {
252 | continue;
253 | }
254 | if (OrigMeshes.ContainsKey(sharedMesh))
255 | {
256 | continue;
257 | }
258 | Mesh copyMesh = Instantiate(sharedMesh);
259 | if (!sharedMesh.isReadable)
260 | {
261 | Deformers.Logger.LogWarning("Cannot deform " + sharedMesh.name + ", not read/write enabled.");
262 | copyMesh = sharedMesh;
263 | }
264 | OrigMeshes.Add(copyMesh, sharedMesh);
265 | String name = sharedMesh.name;
266 | copyMesh.name = name;
267 | SetMesh(renderer, copyMesh);
268 |
269 | if (!sharedMesh.isReadable)
270 | {
271 | continue;
272 | }
273 | copyMesh.GetNormals(normals);
274 | copyMesh.RecalculateNormals();
275 | copyMesh.GetNormals(newNormals);
276 | Quaternion[] normalDiffs = new Quaternion[newNormals.Count];
277 | for (int i = 0; i < normals.Count; i++)
278 | {
279 | normalDiffs[i] = Quaternion.FromToRotation(newNormals[i], normals[i]);
280 | }
281 | NormalDiffs.Add(copyMesh, normalDiffs);
282 | copyMesh.SetNormals(normals);
283 |
284 | Dictionary duplicateCheck = new Dictionary();
285 | sharedMesh.GetVertices(origVertices);
286 | int[] duplicates = new int[origVertices.Count];
287 | for (int i = 0; i < origVertices.Count; i++)
288 | {
289 | if (duplicateCheck.ContainsKey(origVertices[i]))
290 | {
291 | duplicates[i] = duplicateCheck[origVertices[i]];
292 | }
293 | else
294 | {
295 | duplicateCheck.Add(origVertices[i], i);
296 | }
297 | }
298 | DuplicateVectors.Add(copyMesh, duplicates);
299 | }
300 |
301 | if (reload)
302 | {
303 | PluginData deformData = GetExtendedData();
304 | if (deformData != null)
305 | {
306 | foreach (Component renderer in Renderers)
307 | {
308 | if (renderer == null)
309 | {
310 | continue;
311 | }
312 | Mesh sharedMesh = GetMesh(renderer);
313 | if (sharedMesh == null)
314 | {
315 | continue;
316 | }
317 | if (!sharedMesh.isReadable)
318 | {
319 | continue;
320 | }
321 | sharedMesh.GetVertices(newVertices);
322 | if (deformData.data.TryGetValue(GetPartialHierarchyPath(renderer.transform) + newVertices.Count, out object t))
323 | {
324 | List savedVertices = MessagePackSerializer.Deserialize>((byte[])t, MessagePack.Resolvers.ContractlessStandardResolver.Instance);
325 | for (var i = 0; i < savedVertices.Count; i++)
326 | {
327 | float[] savedVertex = savedVertices[i];
328 | newVertices[(int)savedVertex[0]] = new Vector3(savedVertex[1], savedVertex[2], savedVertex[3]);
329 | }
330 |
331 | sharedMesh.SetVertices(newVertices);
332 |
333 | sharedMesh.RecalculateNormals();
334 | sharedMesh.GetNormals(newNormals);
335 | NativeArray nativeNewNormals = new NativeArray(newNormals.ToArray(), Allocator.Temp);
336 | NativeArray nativeReadOnlyNewNormals = new NativeArray(nativeNewNormals, Allocator.Temp);
337 | Quaternion[] normalDiffs = NormalDiffs[sharedMesh];
338 | NativeArray nativeNormalDiffs = new NativeArray(normalDiffs, Allocator.Temp);
339 | int[] duplicates = DuplicateVectors[sharedMesh];
340 | NativeArray nativeDuplicates = new NativeArray(duplicates, Allocator.Temp);
341 |
342 | NormalDiffsJob normalDiffsJob = new NormalDiffsJob
343 | {
344 | nativeNewNormals = nativeNewNormals,
345 | nativeReadOnlyNewNormals = nativeReadOnlyNewNormals,
346 | nativeNormalDiffs = nativeNormalDiffs
347 | };
348 | JobHandle diffsHandle = normalDiffsJob.Schedule(nativeNewNormals.Length, 32);
349 |
350 | DuplicatesJob duplicatesJob = new DuplicatesJob
351 | {
352 | nativeNewNormals = nativeNewNormals,
353 | nativeReadOnlyNewNormals = nativeReadOnlyNewNormals,
354 | nativeDuplicates = nativeDuplicates
355 | };
356 | JobHandle duplicatesHandle = duplicatesJob.Schedule(nativeNewNormals.Length, 32, diffsHandle);
357 | duplicatesHandle.Complete();
358 | newNormals.Clear();
359 | newNormals.AddRange(nativeNewNormals);
360 | sharedMesh.SetNormals(newNormals);
361 | }
362 | }
363 | }
364 | loaded = true;
365 | loadedTime = Time.time;
366 | }
367 |
368 | if (deform)
369 | {
370 | StartCoroutine(WaitDeform());
371 | }
372 | }
373 |
374 | public void DeformAll()
375 | {
376 | if (loaded == false)
377 | {
378 | return;
379 | }
380 | if ((Time.time - loadedTime) < 1)
381 | {
382 | return;
383 | }
384 | if (DeformerList == null || Renderers == null)
385 | {
386 | return;
387 | }
388 | NativeArray HandeList = new NativeArray(Renderers.Length, Allocator.Temp);
389 | for (int i = 0; i < Renderers.Length; i++) {
390 |
391 | Renderer renderer = (Renderer)Renderers[i];
392 | if (renderer == null)
393 | {
394 | continue;
395 | }
396 | Mesh sharedMesh = GetMesh(renderer);
397 | if (sharedMesh == null)
398 | {
399 | continue;
400 | }
401 | if (!OrigMeshes.ContainsKey(sharedMesh))
402 | {
403 | continue;
404 | }
405 | if (!sharedMesh.isReadable)
406 | {
407 | continue;
408 | }
409 |
410 | OrigMeshes[sharedMesh].GetVertices(newVertices);
411 | sharedMesh.SetVertices(newVertices);
412 | OrigMeshes[sharedMesh].GetNormals(normals);
413 | sharedMesh.SetNormals(normals);
414 |
415 | bool skip = true;
416 | foreach (Deformer deformer in DeformerList)
417 | {
418 | if (deformer.FilterMaterial.shader.name != "Standard")
419 | {
420 | foreach (Material material in ((Renderer)renderer).materials)
421 | {
422 | if (material.shader.name == deformer.FilterMaterial.shader.name)
423 | {
424 | skip = false;
425 | break;
426 | }
427 | }
428 | if (skip == false) break;
429 | }
430 | else
431 | {
432 | skip = false;
433 | break;
434 | }
435 | }
436 | if (skip) continue;
437 |
438 | Transform rendererTransform = renderer.transform;
439 | Transform parent = rendererTransform.parent;
440 | Vector3 localScale = rendererTransform.localScale;
441 |
442 | Matrix4x4[] boneMatrices = null;
443 | BoneWeight[] boneWeights = null;
444 | NativeArray nativeNewVertices = new NativeArray(newVertices.ToArray(), Allocator.Temp);
445 | NativeArray nativeboneMatrices = default;
446 | NativeArray nativeBoneWeights = default;
447 |
448 | Matrix4x4 rootBoneWorldToLocalMatrix = new Matrix4x4();
449 | bool skinned = false;
450 |
451 | if (renderer is SkinnedMeshRenderer skinnedMeshRenderer)
452 | {
453 | skinned = true;
454 |
455 | rendererTransform.parent = null;
456 | localScale = rendererTransform.localScale;
457 | rendererTransform.localScale = Vector3.one;
458 |
459 | Transform[] skinnedBones = skinnedMeshRenderer.bones;
460 | boneMatrices = new Matrix4x4[skinnedBones.Length];
461 | boneWeights = skinnedMeshRenderer.sharedMesh.boneWeights;
462 | Matrix4x4[] meshBindposes = skinnedMeshRenderer.sharedMesh.bindposes;
463 |
464 | if (boneWeights.Length > 0)
465 | {
466 | skinnedMeshRenderer.BakeMesh(bakedMesh);
467 | bakedMesh.GetVertices(bakedVertices);
468 |
469 | for (int j = 0; j < boneMatrices.Length; j++)
470 | {
471 | if (skinnedBones[j] != null && meshBindposes[j] != null)
472 | {
473 | boneMatrices[j] = skinnedBones[j].localToWorldMatrix * meshBindposes[j];
474 | }
475 | else
476 | {
477 | boneMatrices[j] = Matrix4x4.identity;
478 | }
479 | }
480 | nativeboneMatrices = new NativeArray(boneMatrices, Allocator.Temp);
481 | nativeBoneWeights = new NativeArray(boneWeights, Allocator.Temp);
482 | }
483 | else
484 | {
485 | bakedVertices = new List(newVertices);
486 | Transform rootBone = skinnedMeshRenderer.rootBone;
487 | rootBoneWorldToLocalMatrix = rootBone.worldToLocalMatrix;
488 | for (int j = 0; j < bakedVertices.Count; j++)
489 | {
490 | bakedVertices[j] = rootBone.TransformPoint(bakedVertices[j]);
491 | bakedVertices[j] = rendererTransform.InverseTransformPoint(bakedVertices[j]);
492 | }
493 | }
494 | }
495 | else if (renderer is MeshRenderer meshRenderer)
496 | {
497 | bakedVertices = new List(newVertices);
498 | for (int j = 0; j < bakedVertices.Count; j++)
499 | {
500 | bakedVertices[j] = rendererTransform.TransformPoint(bakedVertices[j]);
501 | }
502 | }
503 | else
504 | {
505 | continue;
506 | }
507 |
508 | NativeArray nativeBakedVertices = new NativeArray(bakedVertices.ToArray(), Allocator.Temp);
509 | NativeArray deformed = new NativeArray(1, Allocator.Temp);
510 | deformed[0] = false;
511 | NativeArray nativeNormals = new NativeArray(normals.ToArray(), Allocator.Temp);
512 | foreach (Deformer deformer in DeformerList)
513 | {
514 | if (!deformer.gameObject.activeInHierarchy)
515 | {
516 | continue;
517 | }
518 | if (deformer.FilterMaterial.shader.name != "Standard")
519 | {
520 | foreach (Material material in (renderer).materials)
521 | {
522 | if (material.shader.name == deformer.FilterMaterial.shader.name)
523 | {
524 | deformer.Deform(nativeNewVertices, nativeBakedVertices, nativeboneMatrices, nativeBoneWeights, rendererTransform.localToWorldMatrix, rendererTransform.worldToLocalMatrix, rootBoneWorldToLocalMatrix, skinned, deformed, nativeNormals);
525 | break;
526 | }
527 | }
528 | }
529 | else
530 | {
531 | deformer.Deform(nativeNewVertices, nativeBakedVertices, nativeboneMatrices, nativeBoneWeights, rendererTransform.localToWorldMatrix, rendererTransform.worldToLocalMatrix, rootBoneWorldToLocalMatrix, skinned, deformed, nativeNormals);
532 | }
533 | }
534 |
535 | rendererTransform.localScale = localScale;
536 | rendererTransform.parent = parent;
537 | if (!deformed[0])
538 | {
539 | continue;
540 | }
541 | newVertices.Clear();
542 | newVertices.AddRange(nativeNewVertices);
543 | sharedMesh.SetVertices(newVertices);
544 |
545 | sharedMesh.RecalculateNormals();
546 | sharedMesh.GetNormals(newNormals);
547 | NativeArray nativeNewNormals = new NativeArray(newNormals.ToArray(), Allocator.Temp);
548 | NativeArray nativeReadOnlyNewNormals = new NativeArray(nativeNewNormals, Allocator.Temp);
549 | Quaternion[] normalDiffs = NormalDiffs[sharedMesh];
550 | NativeArray nativeNormalDiffs = new NativeArray(normalDiffs, Allocator.Temp);
551 | int[] duplicates = DuplicateVectors[sharedMesh];
552 | NativeArray nativeDuplicates = new NativeArray(duplicates, Allocator.Temp);
553 |
554 | NormalDiffsJob normalDiffsJob = new NormalDiffsJob
555 | {
556 | nativeNewNormals = nativeNewNormals,
557 | nativeReadOnlyNewNormals = nativeReadOnlyNewNormals,
558 | nativeNormalDiffs = nativeNormalDiffs
559 | };
560 | JobHandle diffsHandle = normalDiffsJob.Schedule(nativeNewNormals.Length, 32);
561 |
562 | DuplicatesJob duplicatesJob = new DuplicatesJob
563 | {
564 | nativeNewNormals = nativeNewNormals,
565 | nativeReadOnlyNewNormals = nativeReadOnlyNewNormals,
566 | nativeDuplicates = nativeDuplicates
567 | };
568 | JobHandle duplicatesHandle = duplicatesJob.Schedule(nativeNewNormals.Length, 32, diffsHandle);
569 | HandeList[i] = duplicatesHandle;
570 | ResultList.Add(sharedMesh, nativeNewNormals);
571 | }
572 | JobHandle.CompleteAll(HandeList);
573 | foreach (KeyValuePair> result in ResultList)
574 | {
575 | newNormals.Clear();
576 | newNormals.AddRange(result.Value);
577 | result.Key.SetNormals(newNormals);
578 | }
579 | ResultList.Clear();
580 | }
581 |
582 | [BurstCompile]
583 | public struct NormalDiffsJob : IJobParallelFor
584 | {
585 | public NativeArray nativeNewNormals;
586 | public NativeArray nativeReadOnlyNewNormals;
587 | public NativeArray nativeNormalDiffs;
588 |
589 | public void Execute(int index)
590 | {
591 | nativeNewNormals[index] = nativeNormalDiffs[index] * nativeNewNormals[index];
592 | nativeReadOnlyNewNormals[index] = nativeNewNormals[index];
593 | }
594 | }
595 |
596 | [BurstCompile]
597 | public struct DuplicatesJob : IJobParallelFor
598 | {
599 | public NativeArray nativeNewNormals;
600 | public NativeArray nativeReadOnlyNewNormals;
601 | public NativeArray nativeDuplicates;
602 |
603 | public void Execute(int index)
604 | {
605 | if (nativeDuplicates[index] != 0)
606 | {
607 | nativeNewNormals[index] = nativeReadOnlyNewNormals[nativeDuplicates[index]];
608 | }
609 | }
610 | }
611 |
612 | internal void AddDeformer(Deformer deformer)
613 | {
614 | if (DeformerList == null)
615 | {
616 | DeformerList = new List();
617 | }
618 | DeformerList.Add(deformer);
619 | DeformerList.Sort((x, y) => x.AccessoryIndex.CompareTo(y.AccessoryIndex)); //sort deformers top to bottom
620 | StartCoroutine(WaitDeform());
621 | }
622 |
623 | internal void RemoveDeformer(Deformer deformer)
624 | {
625 | DeformerList.Remove(deformer);
626 | if (gameObject.activeInHierarchy)
627 | {
628 | StartCoroutine(WaitDeform());
629 | }
630 | }
631 | internal IEnumerator WaitDeform() //when stuff happens before skinning
632 | {
633 | yield return new WaitForEndOfFrame();
634 | DeformAll();
635 | }
636 | }
637 |
638 | public abstract class Deformer : MonoBehaviour
639 | {
640 | public Transform N1;
641 | public Transform N2;
642 | public Transform SphereA;
643 | public Transform SphereB;
644 | private Vector3 oldN1Position = Vector3.zero;
645 | private Vector3 oldN1Rotation = Vector3.zero;
646 | private Vector3 oldN1Scale = Vector3.zero;
647 | private Vector3 oldN2Position = Vector3.zero;
648 | private Vector3 oldN2Rotation = Vector3.zero;
649 | private Vector3 oldN2Scale = Vector3.zero;
650 | public DeformersController deformersController;
651 | public int AccessoryIndex { get; internal set; }
652 | public Material FilterMaterial { get; internal set; }
653 | public string oldShaderName { get; internal set; }
654 | public float radius = 1.09f;
655 | public float falloff = 1;
656 | public float strength = 0.2f;
657 | public float axisWeight = 1f;
658 | public float height = 1f;
659 | public Vector3 point1;
660 | public Vector3 point2;
661 | public Vector3 sphereA;
662 | public Vector3 sphereB;
663 | public SelectorType selectorType = SelectorType.Sphere;
664 |
665 | public enum SelectorType
666 | {
667 | Sphere,
668 | Capsule
669 | }
670 |
671 | void Start()
672 | {
673 | N1 = GetComponent().trfMove01;
674 | N2 = GetComponent().trfMove02;
675 |
676 | FilterMaterial = ((Renderer)N1.GetComponentInChildren(true)).materials[0]; //renderer is disabled when alpha = 0
677 | oldShaderName = FilterMaterial.shader.name;
678 |
679 | oldN1Position = N1.localPosition;
680 | oldN1Rotation = N1.localEulerAngles;
681 | oldN1Scale = N1.localScale;
682 |
683 | oldN2Position = N2.localPosition;
684 | oldN2Rotation = N2.localEulerAngles;
685 | oldN2Scale = N2.localScale;
686 |
687 | Transform ancestor = transform;
688 | while (ancestor.parent != null)
689 | {
690 | ancestor = ancestor.parent;
691 | if (ancestor.GetComponent() != null)
692 | {
693 | deformersController = ancestor.GetComponent();
694 | break;
695 | }
696 | }
697 | AccessoryIndex = AccessoriesApi.GetAccessoryIndex(deformersController.GetComponent(), gameObject);
698 | deformersController.AddDeformer(this);
699 | }
700 |
701 | void OnDestroy()
702 | {
703 | deformersController.RemoveDeformer(this);
704 | }
705 |
706 | void OnDisable()
707 | {
708 | deformersController.DeformAll();
709 | }
710 |
711 | void OnEnable()
712 | {
713 | if(deformersController != null)
714 | {
715 | deformersController.DeformAll();
716 | }
717 | }
718 |
719 | void Update()
720 | {
721 | if (N1.localScale != oldN1Scale)
722 | {
723 | Vector3[,] addMove = deformersController.GetComponent().nowCoordinate.accessory.parts[AccessoryIndex].addMove;
724 | Vector3 scale = N1.localScale;
725 | if (selectorType == SelectorType.Sphere)
726 | {
727 | scale = new Vector3(N1.localScale.x, N1.localScale.x, N1.localScale.x);
728 | N1.localScale = scale;
729 | }
730 | if (selectorType == SelectorType.Capsule)
731 | {
732 | scale = new Vector3(N1.localScale.x, N1.localScale.y, N1.localScale.x);
733 | N1.localScale = scale;
734 | SphereA.localScale = new Vector3(1 / N1.localScale.x, 1 / N1.localScale.y, 1 / N1.localScale.z) * N1.localScale.x;
735 | SphereB.localScale = SphereA.localScale;
736 | }
737 | addMove[0, 2] = scale;
738 | deformersController.GetComponent().nowCoordinate.accessory.parts[AccessoryIndex].addMove = addMove;
739 | N1.localScale = scale;
740 | if (MakerAPI.InsideMaker)
741 | {
742 | AccessoriesApi.GetCvsAccessory().UpdateCustomUI();
743 | }
744 | deformersController.DeformAll();
745 | }
746 | else if (N1.localPosition != oldN1Position || N1.localEulerAngles != oldN1Rotation ||
747 | N2.localPosition != oldN2Position || N2.localEulerAngles != oldN2Rotation || N2.localScale != oldN2Scale ||
748 | oldShaderName != FilterMaterial.shader.name)
749 | {
750 | deformersController.DeformAll();
751 | }
752 |
753 | oldN1Position = N1.localPosition;
754 | oldN1Rotation = N1.localEulerAngles;
755 | oldN1Scale = N1.localScale;
756 |
757 | oldN2Position = N2.localPosition;
758 | oldN2Rotation = N2.localEulerAngles;
759 | oldN2Scale = N2.localScale;
760 |
761 | oldShaderName = FilterMaterial.shader.name;
762 | }
763 |
764 | public abstract void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeBoneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals);
765 |
766 | public static Matrix4x4 GetReverseSkinningMatrix(NativeArray boneMatrices, BoneWeight weight)
767 | {
768 | Matrix4x4 bm0;
769 | Matrix4x4 bm1;
770 | Matrix4x4 bm2;
771 | Matrix4x4 bm3;
772 | Matrix4x4 reverseSkinningMatrix = new Matrix4x4();
773 | bm0 = boneMatrices[weight.boneIndex0].inverse;
774 | bm1 = boneMatrices[weight.boneIndex1].inverse;
775 | bm2 = boneMatrices[weight.boneIndex2].inverse;
776 | bm3 = boneMatrices[weight.boneIndex3].inverse;
777 |
778 | reverseSkinningMatrix.m00 = bm0.m00 * weight.weight0 + bm1.m00 * weight.weight1 + bm2.m00 * weight.weight2 + bm3.m00 * weight.weight3;
779 | reverseSkinningMatrix.m01 = bm0.m01 * weight.weight0 + bm1.m01 * weight.weight1 + bm2.m01 * weight.weight2 + bm3.m01 * weight.weight3;
780 | reverseSkinningMatrix.m02 = bm0.m02 * weight.weight0 + bm1.m02 * weight.weight1 + bm2.m02 * weight.weight2 + bm3.m02 * weight.weight3;
781 | reverseSkinningMatrix.m03 = bm0.m03 * weight.weight0 + bm1.m03 * weight.weight1 + bm2.m03 * weight.weight2 + bm3.m03 * weight.weight3;
782 |
783 | reverseSkinningMatrix.m10 = bm0.m10 * weight.weight0 + bm1.m10 * weight.weight1 + bm2.m10 * weight.weight2 + bm3.m10 * weight.weight3;
784 | reverseSkinningMatrix.m11 = bm0.m11 * weight.weight0 + bm1.m11 * weight.weight1 + bm2.m11 * weight.weight2 + bm3.m11 * weight.weight3;
785 | reverseSkinningMatrix.m12 = bm0.m12 * weight.weight0 + bm1.m12 * weight.weight1 + bm2.m12 * weight.weight2 + bm3.m12 * weight.weight3;
786 | reverseSkinningMatrix.m13 = bm0.m13 * weight.weight0 + bm1.m13 * weight.weight1 + bm2.m13 * weight.weight2 + bm3.m13 * weight.weight3;
787 |
788 | reverseSkinningMatrix.m20 = bm0.m20 * weight.weight0 + bm1.m20 * weight.weight1 + bm2.m20 * weight.weight2 + bm3.m20 * weight.weight3;
789 | reverseSkinningMatrix.m21 = bm0.m21 * weight.weight0 + bm1.m21 * weight.weight1 + bm2.m21 * weight.weight2 + bm3.m21 * weight.weight3;
790 | reverseSkinningMatrix.m22 = bm0.m22 * weight.weight0 + bm1.m22 * weight.weight1 + bm2.m22 * weight.weight2 + bm3.m22 * weight.weight3;
791 | reverseSkinningMatrix.m23 = bm0.m23 * weight.weight0 + bm1.m23 * weight.weight1 + bm2.m23 * weight.weight2 + bm3.m23 * weight.weight3;
792 |
793 | return reverseSkinningMatrix;
794 | }
795 |
796 | public static Vector3 BakedToNewVertex(Vector3 bakedVertex, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, NativeArray boneMatrices, NativeArray boneWeights, int index, bool skinned)
797 | {
798 | Vector3 newVertex;
799 | if (skinned == false)
800 | {
801 | newVertex = RendererWorldToLocalMatrix.MultiplyPoint3x4(bakedVertex);
802 | return newVertex;
803 | }
804 | if (boneWeights.Length > 0)
805 | {
806 | BoneWeight weight = boneWeights[index];
807 | Matrix4x4 reverseSkinningMatrix = GetReverseSkinningMatrix(boneMatrices, weight);
808 | newVertex = reverseSkinningMatrix.MultiplyPoint3x4(RendererLocalToWorldMatrix.MultiplyPoint3x4(bakedVertex));
809 | }
810 | else
811 | {
812 | Vector3 v = RendererLocalToWorldMatrix.MultiplyPoint3x4(bakedVertex);
813 | newVertex = RootBoneWorldToLocalMatrix.MultiplyPoint3x4(v);
814 | }
815 | return newVertex;
816 | }
817 |
818 | public void SetDeformParams()
819 | {
820 | radius = N1.localScale.x / 2;
821 | strength = N2.localScale.x;
822 | height = (N1.localScale.y / 2) + radius;
823 | falloff = N2.localScale.y;
824 | axisWeight = N2.localScale.z;
825 | if (falloff == 0.01f)
826 | {
827 | falloff = 0f;
828 | }
829 | if (strength == 0.01f)
830 | {
831 | strength = 0f;
832 | }
833 | if (axisWeight == 0.01f)
834 | {
835 | axisWeight = 0f;
836 | }
837 | }
838 |
839 | public void SetPoints(Matrix4x4 RendererWorldToLocalMatrix, bool skinned)
840 | {
841 | point1 = N1.position;
842 | point2 = N2.position;
843 | if (skinned)
844 | {
845 | point1 = RendererWorldToLocalMatrix.MultiplyPoint3x4(point1);
846 | point2 = RendererWorldToLocalMatrix.MultiplyPoint3x4(point2);
847 | }
848 | if (selectorType == SelectorType.Capsule)
849 | {
850 | sphereA = SphereA.position;
851 | sphereB = SphereB.position;
852 | if (skinned)
853 | {
854 | sphereA = RendererWorldToLocalMatrix.MultiplyPoint3x4(sphereA);
855 | sphereB = RendererWorldToLocalMatrix.MultiplyPoint3x4(sphereB);
856 | }
857 | }
858 | }
859 | }
860 |
861 | public class Expander : Deformer
862 | {
863 | [BurstCompile]
864 | public struct DeformJob : IJobParallelFor
865 | {
866 | public float radius;
867 | public float falloff;
868 | public float strength;
869 | public NativeArray nativeNewVertices;
870 | public NativeArray nativeBakedVertices;
871 | public Vector3 point1;
872 | public Vector3 point2;
873 | public NativeArray nativeboneMatrices;
874 | public NativeArray nativeBoneWeights;
875 | public Matrix4x4 RendererWorldToLocalMatrix;
876 | public Matrix4x4 RendererLocalToWorldMatrix;
877 | public Matrix4x4 RootBoneWorldToLocalMatrix;
878 | public bool skinned;
879 | public NativeArray deformed;
880 | public SelectorType selectorType;
881 | public Vector3 sphereA;
882 | public Vector3 sphereB;
883 | public float height;
884 | public float axisWeight;
885 | public NativeArray nativeNormals;
886 |
887 | public void Execute(int index)
888 | {
889 | if (selectorType == SelectorType.Sphere)
890 | {
891 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
892 | if (distance < radius)
893 | {
894 | deformed[0] = true;
895 | float factor = 1 - ((distance / radius) * falloff);
896 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], nativeBakedVertices[index] + (nativeNormals[index].normalized / 10), strength * factor);
897 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
898 | }
899 | }
900 | if (selectorType == SelectorType.Capsule)
901 | {
902 | Vector3 sphereVector = sphereB - sphereA;
903 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
904 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
905 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
906 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
907 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
908 | float lengthsq = capsuleVector.sqrMagnitude;
909 | if ((dot > 0f) && (dot < lengthsq))
910 | {
911 | Vector3 closestPointOnAxis;
912 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
913 | if (f < 0)
914 | {
915 | closestPointOnAxis = sphereA;
916 | }
917 | else if (f > sphereVector.magnitude)
918 | {
919 | closestPointOnAxis = sphereB;
920 | }
921 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
922 |
923 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
924 | if (axisDistance < radius)
925 | {
926 | deformed[0] = true;
927 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
928 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
929 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
930 |
931 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
932 | float centerFactor = 1 - ((centerDistance / height) * falloff);
933 |
934 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
935 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], nativeBakedVertices[index] + (nativeNormals[index].normalized / 10), strength * factor);
936 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
937 | }
938 | }
939 | }
940 | }
941 | }
942 |
943 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
944 | {
945 | SetDeformParams();
946 | SetPoints(RendererWorldToLocalMatrix, skinned);
947 |
948 | DeformJob deformJob = new DeformJob
949 | {
950 | nativeNewVertices = nativeNewVertices,
951 | nativeBakedVertices = nativeBakedVertices,
952 | radius = radius,
953 | falloff = falloff,
954 | strength = strength,
955 | point1 = point1,
956 | point2 = point2,
957 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
958 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
959 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
960 | nativeBoneWeights = nativeBoneWeights,
961 | nativeboneMatrices = nativeboneMatrices,
962 | skinned = skinned,
963 | deformed = deformed,
964 | selectorType = selectorType,
965 | sphereA = sphereA,
966 | sphereB = sphereB,
967 | axisWeight = axisWeight,
968 | height = height,
969 | nativeNormals = nativeNormals
970 | };
971 |
972 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
973 | jobHandle.Complete();
974 | }
975 | }
976 |
977 | public class Shrinker : Deformer
978 | {
979 | [BurstCompile]
980 | public struct DeformJob : IJobParallelFor
981 | {
982 | public float radius;
983 | public float falloff;
984 | public float strength;
985 | public NativeArray nativeNewVertices;
986 | public NativeArray nativeBakedVertices;
987 | public Vector3 point1;
988 | public Vector3 point2;
989 | public NativeArray nativeboneMatrices;
990 | public NativeArray nativeBoneWeights;
991 | public Matrix4x4 RendererWorldToLocalMatrix;
992 | public Matrix4x4 RendererLocalToWorldMatrix;
993 | public Matrix4x4 RootBoneWorldToLocalMatrix;
994 | public bool skinned;
995 | public NativeArray deformed;
996 | public SelectorType selectorType;
997 | public Vector3 sphereA;
998 | public Vector3 sphereB;
999 | public float height;
1000 | public float axisWeight;
1001 | public NativeArray nativeNormals;
1002 |
1003 | public void Execute(int index)
1004 | {
1005 | if (selectorType == SelectorType.Sphere)
1006 | {
1007 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
1008 | if (distance < radius)
1009 | {
1010 | deformed[0] = true;
1011 | float factor = 1 - ((distance / radius) * falloff);
1012 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], nativeBakedVertices[index] - (nativeNormals[index].normalized/10), strength * factor);
1013 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1014 | }
1015 | }
1016 | if (selectorType == SelectorType.Capsule)
1017 | {
1018 | Vector3 sphereVector = sphereB - sphereA;
1019 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
1020 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
1021 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
1022 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
1023 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
1024 | float lengthsq = capsuleVector.sqrMagnitude;
1025 | if ((dot > 0f) && (dot < lengthsq))
1026 | {
1027 | Vector3 closestPointOnAxis;
1028 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
1029 | if (f < 0)
1030 | {
1031 | closestPointOnAxis = sphereA;
1032 | }
1033 | else if (f > sphereVector.magnitude)
1034 | {
1035 | closestPointOnAxis = sphereB;
1036 | }
1037 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1038 |
1039 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1040 | if (axisDistance < radius)
1041 | {
1042 | deformed[0] = true;
1043 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1044 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1045 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
1046 |
1047 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
1048 | float centerFactor = 1 - ((centerDistance / height) * falloff);
1049 |
1050 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
1051 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], nativeBakedVertices[index] - (nativeNormals[index].normalized/10), strength * factor);
1052 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1053 | }
1054 | }
1055 | }
1056 | }
1057 | }
1058 |
1059 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
1060 | {
1061 | SetDeformParams();
1062 | SetPoints(RendererWorldToLocalMatrix, skinned);
1063 |
1064 | DeformJob deformJob = new DeformJob
1065 | {
1066 | nativeNewVertices = nativeNewVertices,
1067 | nativeBakedVertices = nativeBakedVertices,
1068 | radius = radius,
1069 | falloff = falloff,
1070 | strength = strength,
1071 | point1 = point1,
1072 | point2 = point2,
1073 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
1074 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
1075 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
1076 | nativeBoneWeights = nativeBoneWeights,
1077 | nativeboneMatrices = nativeboneMatrices,
1078 | skinned = skinned,
1079 | deformed = deformed,
1080 | selectorType = selectorType,
1081 | sphereA = sphereA,
1082 | sphereB = sphereB,
1083 | axisWeight = axisWeight,
1084 | height = height,
1085 | nativeNormals = nativeNormals
1086 | };
1087 |
1088 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
1089 | jobHandle.Complete();
1090 | }
1091 | }
1092 |
1093 | public class Squeezer : Deformer
1094 | {
1095 | [BurstCompile]
1096 | public struct DeformJob : IJobParallelFor
1097 | {
1098 | public float radius;
1099 | public float falloff;
1100 | public float strength;
1101 | public NativeArray nativeNewVertices;
1102 | public NativeArray nativeBakedVertices;
1103 | public Vector3 point1;
1104 | public Vector3 point2;
1105 | public NativeArray nativeboneMatrices;
1106 | public NativeArray nativeBoneWeights;
1107 | public Matrix4x4 RendererWorldToLocalMatrix;
1108 | public Matrix4x4 RendererLocalToWorldMatrix;
1109 | public Matrix4x4 RootBoneWorldToLocalMatrix;
1110 | public bool skinned;
1111 | public NativeArray deformed;
1112 | public SelectorType selectorType;
1113 | public Vector3 sphereA;
1114 | public Vector3 sphereB;
1115 | public float height;
1116 | public float axisWeight;
1117 |
1118 | public void Execute(int index)
1119 | {
1120 | if(selectorType == SelectorType.Sphere)
1121 | {
1122 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
1123 | if (distance < radius)
1124 | {
1125 | deformed[0] = true;
1126 | float factor = 1 - ((distance / radius) * falloff);
1127 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], point2, strength * factor);
1128 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1129 | }
1130 | }
1131 | if (selectorType == SelectorType.Capsule)
1132 | {
1133 | Vector3 sphereVector = sphereB - sphereA;
1134 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
1135 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
1136 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
1137 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
1138 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
1139 | float lengthsq = capsuleVector.sqrMagnitude;
1140 | if ((dot > 0f) && (dot < lengthsq))
1141 | {
1142 | Vector3 closestPointOnAxis;
1143 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
1144 | if (f < 0)
1145 | {
1146 | closestPointOnAxis = sphereA;
1147 | }
1148 | else if (f > sphereVector.magnitude)
1149 | {
1150 | closestPointOnAxis = sphereB;
1151 | }
1152 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1153 |
1154 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1155 | if (axisDistance < radius)
1156 | {
1157 | deformed[0] = true;
1158 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1159 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1160 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
1161 |
1162 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
1163 | float centerFactor = 1 - ((centerDistance / height) * falloff);
1164 |
1165 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
1166 | closestPointOnAxis = Vector3.Lerp(closestPointOnAxis, point1, axisWeight);
1167 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], closestPointOnAxis + (point2 - point1), strength * factor);
1168 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1169 | }
1170 | }
1171 | }
1172 | }
1173 | }
1174 |
1175 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
1176 | {
1177 | SetDeformParams();
1178 | SetPoints(RendererWorldToLocalMatrix, skinned);
1179 |
1180 | DeformJob deformJob = new DeformJob
1181 | {
1182 | nativeNewVertices = nativeNewVertices,
1183 | nativeBakedVertices = nativeBakedVertices,
1184 | radius = radius,
1185 | falloff = falloff,
1186 | strength = strength,
1187 | point1 = point1,
1188 | point2 = point2,
1189 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
1190 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
1191 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
1192 | nativeBoneWeights = nativeBoneWeights,
1193 | nativeboneMatrices = nativeboneMatrices,
1194 | skinned = skinned,
1195 | deformed = deformed,
1196 | selectorType = selectorType,
1197 | sphereA = sphereA,
1198 | sphereB = sphereB,
1199 | axisWeight = axisWeight,
1200 | height = height
1201 | };
1202 |
1203 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
1204 | jobHandle.Complete();
1205 | }
1206 | }
1207 |
1208 | public class Bulger : Deformer
1209 | {
1210 |
1211 | [BurstCompile]
1212 | public struct DeformJob : IJobParallelFor
1213 | {
1214 | public float radius;
1215 | public float falloff;
1216 | public float strength;
1217 | public NativeArray nativeNewVertices;
1218 | public NativeArray nativeBakedVertices;
1219 | public Vector3 point1;
1220 | public Vector3 point2;
1221 | public NativeArray nativeboneMatrices;
1222 | public NativeArray nativeBoneWeights;
1223 | public Matrix4x4 RendererWorldToLocalMatrix;
1224 | public Matrix4x4 RendererLocalToWorldMatrix;
1225 | public Matrix4x4 RootBoneWorldToLocalMatrix;
1226 | public bool skinned;
1227 | public NativeArray deformed;
1228 | public SelectorType selectorType;
1229 | public Vector3 sphereA;
1230 | public Vector3 sphereB;
1231 | public float height;
1232 | public float axisWeight;
1233 |
1234 | public void Execute(int index)
1235 | {
1236 | if (selectorType == SelectorType.Sphere)
1237 | {
1238 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
1239 | if (distance < radius)
1240 | {
1241 | deformed[0] = true;
1242 | Vector3 newPoint = nativeBakedVertices[index] + (nativeBakedVertices[index] - point2);
1243 | float factor = 1 - ((distance / radius) * falloff);
1244 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1245 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1246 | }
1247 | }
1248 | if (selectorType == SelectorType.Capsule)
1249 | {
1250 | Vector3 sphereVector = sphereB - sphereA;
1251 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
1252 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
1253 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
1254 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
1255 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
1256 | float lengthsq = capsuleVector.sqrMagnitude;
1257 | if ((dot > 0f) && (dot < lengthsq))
1258 | {
1259 | Vector3 closestPointOnAxis;
1260 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
1261 | if (f < 0)
1262 | {
1263 | closestPointOnAxis = sphereA;
1264 | }
1265 | else if (f > sphereVector.magnitude)
1266 | {
1267 | closestPointOnAxis = sphereB;
1268 | }
1269 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1270 |
1271 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1272 | if (axisDistance < radius)
1273 | {
1274 | deformed[0] = true;
1275 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1276 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1277 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
1278 |
1279 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
1280 | float centerFactor = 1 - ((centerDistance / height) * falloff);
1281 |
1282 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
1283 | closestPointOnAxis = Vector3.Lerp(closestPointOnAxis, point1, axisWeight);
1284 | Vector3 newPoint = nativeBakedVertices[index] + (nativeBakedVertices[index] - (closestPointOnAxis + (point2 - point1)));
1285 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1286 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1287 | }
1288 | }
1289 | }
1290 | }
1291 | }
1292 |
1293 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
1294 | {
1295 | SetDeformParams();
1296 | SetPoints(RendererWorldToLocalMatrix, skinned);
1297 |
1298 | DeformJob deformJob = new DeformJob
1299 | {
1300 | nativeNewVertices = nativeNewVertices,
1301 | nativeBakedVertices = nativeBakedVertices,
1302 | radius = radius,
1303 | falloff = falloff,
1304 | strength = strength,
1305 | point1 = point1,
1306 | point2 = point2,
1307 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
1308 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
1309 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
1310 | nativeBoneWeights = nativeBoneWeights,
1311 | nativeboneMatrices = nativeboneMatrices,
1312 | skinned = skinned,
1313 | deformed = deformed,
1314 | selectorType = selectorType,
1315 | sphereA = sphereA,
1316 | sphereB = sphereB,
1317 | axisWeight = axisWeight,
1318 | height = height
1319 | };
1320 |
1321 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
1322 | jobHandle.Complete();
1323 | }
1324 | }
1325 |
1326 | public class Mover : Deformer
1327 | {
1328 | [BurstCompile]
1329 | public struct DeformJob : IJobParallelFor
1330 | {
1331 | public float radius;
1332 | public float falloff;
1333 | public float strength;
1334 | public NativeArray nativeNewVertices;
1335 | public NativeArray nativeBakedVertices;
1336 | public Vector3 point1;
1337 | public Vector3 point2;
1338 | public NativeArray nativeboneMatrices;
1339 | public NativeArray nativeBoneWeights;
1340 | public Matrix4x4 RendererWorldToLocalMatrix;
1341 | public Matrix4x4 RendererLocalToWorldMatrix;
1342 | public Matrix4x4 RootBoneWorldToLocalMatrix;
1343 | public Vector3 moveVector;
1344 | public bool skinned;
1345 | public NativeArray deformed;
1346 | public SelectorType selectorType;
1347 | public Vector3 sphereA;
1348 | public Vector3 sphereB;
1349 | public float height;
1350 | public float axisWeight;
1351 |
1352 | public void Execute(int index)
1353 | {
1354 | if (selectorType == SelectorType.Sphere)
1355 | {
1356 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
1357 | if (distance < radius)
1358 | {
1359 | deformed[0] = true;
1360 | Vector3 newPoint = nativeBakedVertices[index] + moveVector;
1361 | float factor = 1 - ((distance / radius) * falloff);
1362 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1363 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1364 | }
1365 | }
1366 | if (selectorType == SelectorType.Capsule)
1367 | {
1368 | Vector3 sphereVector = sphereB - sphereA;
1369 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
1370 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
1371 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
1372 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
1373 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
1374 | float lengthsq = capsuleVector.sqrMagnitude;
1375 | if ((dot > 0f) && (dot < lengthsq))
1376 | {
1377 | Vector3 closestPointOnAxis;
1378 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
1379 | if (f < 0)
1380 | {
1381 | closestPointOnAxis = sphereA;
1382 | }
1383 | else if (f > sphereVector.magnitude)
1384 | {
1385 | closestPointOnAxis = sphereB;
1386 | }
1387 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1388 |
1389 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1390 | if (axisDistance < radius)
1391 | {
1392 | deformed[0] = true;
1393 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1394 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1395 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
1396 |
1397 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
1398 | float centerFactor = 1 - ((centerDistance / height) * falloff);
1399 |
1400 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
1401 | Vector3 newPoint = nativeBakedVertices[index] + moveVector;
1402 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1403 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1404 | }
1405 | }
1406 | }
1407 | }
1408 | }
1409 |
1410 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
1411 | {
1412 | SetDeformParams();
1413 | SetPoints(RendererWorldToLocalMatrix, skinned);
1414 |
1415 | DeformJob deformJob = new DeformJob
1416 | {
1417 | nativeNewVertices = nativeNewVertices,
1418 | nativeBakedVertices = nativeBakedVertices,
1419 | radius = radius,
1420 | falloff = falloff,
1421 | strength = strength,
1422 | point1 = point1,
1423 | point2 = point2,
1424 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
1425 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
1426 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
1427 | nativeBoneWeights = nativeBoneWeights,
1428 | nativeboneMatrices = nativeboneMatrices,
1429 | moveVector = point2 - point1,
1430 | skinned = skinned,
1431 | deformed = deformed,
1432 | selectorType = selectorType,
1433 | sphereA = sphereA,
1434 | sphereB = sphereB,
1435 | axisWeight = axisWeight,
1436 | height = height
1437 | };
1438 |
1439 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
1440 | jobHandle.Complete();
1441 | }
1442 | }
1443 |
1444 | public class Rotator : Deformer
1445 | {
1446 | [BurstCompile]
1447 | public struct DeformJob : IJobParallelFor
1448 | {
1449 | public float radius;
1450 | public float falloff;
1451 | public float strength;
1452 | public NativeArray nativeNewVertices;
1453 | public NativeArray nativeBakedVertices;
1454 | public Vector3 point1;
1455 | public Vector3 point2;
1456 | public NativeArray nativeboneMatrices;
1457 | public NativeArray nativeBoneWeights;
1458 | public Matrix4x4 RendererWorldToLocalMatrix;
1459 | public Matrix4x4 RendererLocalToWorldMatrix;
1460 | public Matrix4x4 RootBoneWorldToLocalMatrix;
1461 | public Vector3 moveVector;
1462 | public bool skinned;
1463 | public Quaternion rotation;
1464 | public NativeArray deformed;
1465 | public SelectorType selectorType;
1466 | public Vector3 sphereA;
1467 | public Vector3 sphereB;
1468 | public float height;
1469 | public float axisWeight;
1470 |
1471 | public void Execute(int index)
1472 | {
1473 |
1474 |
1475 | if (selectorType == SelectorType.Sphere)
1476 | {
1477 | float distance = Vector3.Distance(nativeBakedVertices[index], point1);
1478 | if (distance < radius)
1479 | {
1480 | deformed[0] = true;
1481 | Vector3 newPoint = point2 + (rotation * (nativeBakedVertices[index] - point2));
1482 | float factor = 1 - ((distance / radius) * falloff);
1483 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1484 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1485 | }
1486 | }
1487 | if (selectorType == SelectorType.Capsule)
1488 | {
1489 | Vector3 sphereVector = sphereB - sphereA;
1490 | Vector3 capsuleEndA = sphereA - (radius * sphereVector.normalized);
1491 | Vector3 capsuleEndB = sphereB + (radius * sphereVector.normalized);
1492 | Vector3 capsuleVector = capsuleEndB - capsuleEndA;
1493 | Vector3 p = nativeBakedVertices[index] - capsuleEndA;
1494 | float dot = p.x * capsuleVector.x + p.y * capsuleVector.y + p.z * capsuleVector.z;
1495 | float lengthsq = capsuleVector.sqrMagnitude;
1496 | if ((dot > 0f) && (dot < lengthsq))
1497 | {
1498 | Vector3 closestPointOnAxis;
1499 | float f = Vector3.Dot(nativeBakedVertices[index] - sphereA, sphereVector.normalized);
1500 | if (f < 0)
1501 | {
1502 | closestPointOnAxis = sphereA;
1503 | }
1504 | else if (f > sphereVector.magnitude)
1505 | {
1506 | closestPointOnAxis = sphereB;
1507 | }
1508 | else closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1509 |
1510 | float axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1511 | if (axisDistance < radius)
1512 | {
1513 | deformed[0] = true;
1514 | closestPointOnAxis = sphereA + (f * sphereVector.normalized);
1515 | axisDistance = Vector3.Distance(closestPointOnAxis, nativeBakedVertices[index]);
1516 | float axisFactor = 1 - ((axisDistance / radius) * falloff);
1517 |
1518 | float centerDistance = Vector3.Distance(point1, nativeBakedVertices[index]);
1519 | float centerFactor = 1 - ((centerDistance / height) * falloff);
1520 |
1521 | float factor = Mathf.Lerp(axisFactor, centerFactor, axisWeight);
1522 | closestPointOnAxis = Vector3.Lerp(closestPointOnAxis, point1, axisWeight);
1523 | Vector3 newPoint2 = closestPointOnAxis + (point2 - point1);
1524 | Vector3 newPoint = newPoint2 + (rotation * (nativeBakedVertices[index] - newPoint2));
1525 | nativeBakedVertices[index] = Vector3.Lerp(nativeBakedVertices[index], newPoint, strength * factor);
1526 | nativeNewVertices[index] = BakedToNewVertex(nativeBakedVertices[index], RendererWorldToLocalMatrix, RendererLocalToWorldMatrix, RootBoneWorldToLocalMatrix, nativeboneMatrices, nativeBoneWeights, index, skinned);
1527 | }
1528 | }
1529 | }
1530 | }
1531 | }
1532 |
1533 | public override void Deform(NativeArray nativeNewVertices, NativeArray nativeBakedVertices, NativeArray nativeboneMatrices, NativeArray nativeBoneWeights, Matrix4x4 RendererLocalToWorldMatrix, Matrix4x4 RendererWorldToLocalMatrix, Matrix4x4 RootBoneWorldToLocalMatrix, bool skinned, NativeArray deformed, NativeArray nativeNormals)
1534 | {
1535 | SetDeformParams();
1536 | SetPoints(RendererWorldToLocalMatrix, skinned);
1537 |
1538 | DeformJob deformJob = new DeformJob
1539 | {
1540 | nativeNewVertices = nativeNewVertices,
1541 | nativeBakedVertices = nativeBakedVertices,
1542 | radius = radius,
1543 | falloff = falloff,
1544 | strength = strength,
1545 | point1 = point1,
1546 | point2 = point2,
1547 | RendererLocalToWorldMatrix = RendererLocalToWorldMatrix,
1548 | RendererWorldToLocalMatrix = RendererWorldToLocalMatrix,
1549 | RootBoneWorldToLocalMatrix = RootBoneWorldToLocalMatrix,
1550 | nativeBoneWeights = nativeBoneWeights,
1551 | nativeboneMatrices = nativeboneMatrices,
1552 | moveVector = point2 - point1,
1553 | skinned = skinned,
1554 | rotation = N2.localRotation,
1555 | deformed = deformed,
1556 | selectorType = selectorType,
1557 | sphereA = sphereA,
1558 | sphereB = sphereB,
1559 | axisWeight = axisWeight,
1560 | height = height
1561 | };
1562 |
1563 | JobHandle jobHandle = deformJob.Schedule(nativeNewVertices.Length, 32);
1564 | jobHandle.Complete();
1565 | }
1566 | }
1567 |
--------------------------------------------------------------------------------