Split rigscene into one file per character root and bump to 0.3.0
This commit is contained in:
@@ -20,7 +20,7 @@ Run these in the in-game console.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `rigprobe` | Dump the player, carry bodies, all actor prefabs and live actors |
|
| `rigprobe` | Dump the player, carry bodies, all actor prefabs and live actors |
|
||||||
| `rigprobe <filter>` | Same, limited to actor types containing the filter, e.g. `rigprobe female` |
|
| `rigprobe <filter>` | Same, limited to actor types containing the filter, e.g. `rigprobe female` |
|
||||||
| `rigscene` | Dump every skinned mesh root in the loaded scenes, including cutscene characters |
|
| `rigscene` | Dump every character in the loaded scenes (posers, cutscene characters, props with skinned meshes), one file per character |
|
||||||
| `rigspawn <Type> [variation]` | Spawn an actor in front of you so its live variant gets dumped, e.g. `rigspawn Virginia` |
|
| `rigspawn <Type> [variation]` | Spawn an actor in front of you so its live variant gets dumped, e.g. `rigspawn Virginia` |
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|||||||
+58
-7
@@ -164,16 +164,27 @@ public class RigProbe : SonsMod
|
|||||||
skip.Add(t.GetInstanceID());
|
skip.Add(t.GetInstanceID());
|
||||||
|
|
||||||
var roots = new Dictionary<int, Transform>();
|
var roots = new Dictionary<int, Transform>();
|
||||||
|
var members = new Dictionary<int, List<SkinnedMeshRenderer>>();
|
||||||
foreach (var smr in Resources.FindObjectsOfTypeAll<SkinnedMeshRenderer>())
|
foreach (var smr in Resources.FindObjectsOfTypeAll<SkinnedMeshRenderer>())
|
||||||
{
|
{
|
||||||
if (!smr || !smr.gameObject.scene.IsValid() || skip.Contains(smr.transform.GetInstanceID()))
|
if (!smr || !smr.gameObject.scene.IsValid() || skip.Contains(smr.transform.GetInstanceID()))
|
||||||
continue;
|
continue;
|
||||||
var root = smr.transform.root;
|
var root = CharacterRoot(smr);
|
||||||
if (!roots.ContainsKey(root.GetInstanceID()))
|
if (!root)
|
||||||
roots[root.GetInstanceID()] = root;
|
continue;
|
||||||
|
var key = root.GetInstanceID();
|
||||||
|
if (!roots.ContainsKey(key))
|
||||||
|
{
|
||||||
|
roots[key] = root;
|
||||||
|
members[key] = new List<SkinnedMeshRenderer>();
|
||||||
|
}
|
||||||
|
members[key].Add(smr);
|
||||||
|
}
|
||||||
|
foreach (var kv in roots)
|
||||||
|
{
|
||||||
|
var root = kv.Value;
|
||||||
|
dumps.Add(DumpObject(root.gameObject, "scene", $"{root.name}_{kv.Key}", null, members[kv.Key]));
|
||||||
}
|
}
|
||||||
foreach (var root in roots.Values)
|
|
||||||
dumps.Add(DumpObject(root.gameObject, "scene", $"{root.name}_{root.GetInstanceID()}", null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var d in dumps)
|
foreach (var d in dumps)
|
||||||
@@ -189,7 +200,7 @@ public class RigProbe : SonsMod
|
|||||||
Say($"RigProbe: {dumps.Count} characters written to {outDir}");
|
Say($"RigProbe: {dumps.Count} characters written to {outDir}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CharacterDump DumpObject(GameObject go, string source, string name, Transform exclude)
|
private static CharacterDump DumpObject(GameObject go, string source, string name, Transform exclude, List<SkinnedMeshRenderer> only = null)
|
||||||
{
|
{
|
||||||
var root = go.transform;
|
var root = go.transform;
|
||||||
var dump = new CharacterDump
|
var dump = new CharacterDump
|
||||||
@@ -200,7 +211,7 @@ public class RigProbe : SonsMod
|
|||||||
Active = go.activeInHierarchy
|
Active = go.activeInHierarchy
|
||||||
};
|
};
|
||||||
|
|
||||||
var smrs = go.GetComponentsInChildren<SkinnedMeshRenderer>(true)
|
var smrs = only ?? go.GetComponentsInChildren<SkinnedMeshRenderer>(true)
|
||||||
.Where(r => r && !(exclude && IsUnder(r.transform, exclude)))
|
.Where(r => r && !(exclude && IsUnder(r.transform, exclude)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@@ -220,6 +231,8 @@ public class RigProbe : SonsMod
|
|||||||
{
|
{
|
||||||
if (!a || (exclude && IsUnder(a.transform, exclude)))
|
if (!a || (exclude && IsUnder(a.transform, exclude)))
|
||||||
continue;
|
continue;
|
||||||
|
if (only != null && a.transform != root && !rigIds.Contains(a.transform.GetInstanceID()))
|
||||||
|
continue;
|
||||||
AddWithAncestors(a.transform, root, rigIds);
|
AddWithAncestors(a.transform, root, rigIds);
|
||||||
dump.Animators.Add(DumpAnimator(a, root));
|
dump.Animators.Add(DumpAnimator(a, root));
|
||||||
}
|
}
|
||||||
@@ -496,6 +509,44 @@ public class RigProbe : SonsMod
|
|||||||
return $"{hit}/{names.Count} ({hit * 100 / names.Count}%)";
|
return $"{hit}/{names.Count} ({hit * 100 / names.Count}%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Transform CharacterRoot(SkinnedMeshRenderer smr)
|
||||||
|
{
|
||||||
|
var t = smr.transform.parent;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
if (t.GetComponent<Animator>() || t.name.IndexOf("Poser", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
|
return t;
|
||||||
|
t = t.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bone = smr.rootBone;
|
||||||
|
if (!bone && smr.bones != null && smr.bones.Length > 0)
|
||||||
|
bone = smr.bones[0];
|
||||||
|
var lca = CommonAncestor(smr.transform, bone);
|
||||||
|
return lca ? lca : smr.transform.parent ? smr.transform.parent : smr.transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Transform CommonAncestor(Transform a, Transform b)
|
||||||
|
{
|
||||||
|
if (!a || !b)
|
||||||
|
return null;
|
||||||
|
var chain = new HashSet<int>();
|
||||||
|
var t = a;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
chain.Add(t.GetInstanceID());
|
||||||
|
t = t.parent;
|
||||||
|
}
|
||||||
|
t = b;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
if (chain.Contains(t.GetInstanceID()))
|
||||||
|
return t;
|
||||||
|
t = t.parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddWithAncestors(Transform t, Transform root, HashSet<int> ids)
|
private static void AddWithAncestors(Transform t, Transform root, HashSet<int> ids)
|
||||||
{
|
{
|
||||||
while (t)
|
while (t)
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<AssemblyName>RigProbe</AssemblyName>
|
<AssemblyName>RigProbe</AssemblyName>
|
||||||
<RootNamespace>RigProbe</RootNamespace>
|
<RootNamespace>RigProbe</RootNamespace>
|
||||||
<Version>1.0.0</Version>
|
<Version>0.3.0</Version>
|
||||||
<NoWarn>CS0436;CS1701;CS1702;MSB3277;MSB3106</NoWarn>
|
<NoWarn>CS0436;CS1701;CS1702;MSB3277;MSB3106</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
"id": "RigProbe",
|
"id": "RigProbe",
|
||||||
"name": "RigProbe",
|
"name": "RigProbe",
|
||||||
"author": "JustinOros",
|
"author": "JustinOros",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"description": "Dumps rig, mesh, material and animator data for every Sons of the Forest character to JSON for mod development",
|
"description": "Dumps rig, mesh, material and animator data for every Sons of the Forest character to JSON for mod development",
|
||||||
"gameVersion": "1.0.0",
|
"gameVersion": "1.0.0",
|
||||||
"platform": "Client",
|
"platform": "Client",
|
||||||
|
|||||||
Reference in New Issue
Block a user