Initial Commit
This commit is contained in:
parent
9089cf343f
commit
accf7e787f
20 changed files with 623 additions and 0 deletions
8
Editor.meta
Normal file
8
Editor.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 789a1325dbb0b3e48be672f6e2cf7d57
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
287
Editor/Core.cs
Normal file
287
Editor/Core.cs
Normal file
|
|
@ -0,0 +1,287 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using AnimatorAsCode.V1;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using VRC.SDK3.Avatars.Components;
|
||||||
|
using VRC.SDK3.Dynamics.Constraint.Components;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor.Animations;
|
||||||
|
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class AvatarAssets
|
||||||
|
{
|
||||||
|
public AacFlBase aac;
|
||||||
|
public GameObject root;
|
||||||
|
public AacFlController fx;
|
||||||
|
public AacFlClip emptyClip;
|
||||||
|
public bool experimentalEnabled;
|
||||||
|
public bool isPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AvatarUtils
|
||||||
|
{
|
||||||
|
public static GameObject FindChildRecursive(GameObject parent, string name)
|
||||||
|
{
|
||||||
|
return FindChildRecursive(parent.transform, name)?.gameObject;
|
||||||
|
}
|
||||||
|
public static Transform FindChildRecursive(Transform parent, string name)
|
||||||
|
{
|
||||||
|
return parent.GetComponentsInChildren<Transform>(true).FirstOrDefault(t => t.gameObject.name == name);
|
||||||
|
}
|
||||||
|
public static Transform[] FindChildrenRecursive(Transform parent, string name)
|
||||||
|
{
|
||||||
|
return parent.GetComponentsInChildren<Transform>(true).Where(t => t.gameObject.name == name).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AacFlClip CreateConstraintWeightClip(AvatarAssets assets, VRCParentConstraint constraint, int index, int indexCount)
|
||||||
|
{
|
||||||
|
return assets.aac.NewClip()
|
||||||
|
.Animating(action =>
|
||||||
|
{
|
||||||
|
action.Animates(constraint, $"Sources.source{index}.Weight").WithOneFrame(1f);
|
||||||
|
for (int i = 0; i < indexCount; i++)
|
||||||
|
{
|
||||||
|
if (i == index) continue;
|
||||||
|
action.Animates(constraint, $"Sources.source{i}.Weight").WithOneFrame(0f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AacFlClip CreateEmptyClipWithFrames(AvatarAssets assets, int frames)
|
||||||
|
{
|
||||||
|
if (frames == 0) return assets.emptyClip;
|
||||||
|
var emptyGo = new GameObject();
|
||||||
|
emptyGo.name = "_EmptyClipInstant";
|
||||||
|
emptyGo.transform.SetParent(assets.root.transform);
|
||||||
|
var clip = assets.aac.NewClip().Animating(action =>
|
||||||
|
{
|
||||||
|
action.Animates(emptyGo.transform, "m_LocalScale.z").WithFrameCountUnit(unit =>
|
||||||
|
{
|
||||||
|
unit.Constant(0, 0);
|
||||||
|
unit.Constant(frames, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Object.DestroyImmediate(emptyGo);
|
||||||
|
return clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AacFlClip CreateEmptyClipWithSeconds(AvatarAssets assets, float seconds)
|
||||||
|
{
|
||||||
|
if (seconds == 0) return assets.emptyClip;
|
||||||
|
var emptyGo = new GameObject();
|
||||||
|
emptyGo.name = "_EmptyClipInstant";
|
||||||
|
emptyGo.transform.SetParent(assets.root.transform);
|
||||||
|
var clip = assets.aac.NewClip().Animating(action =>
|
||||||
|
{
|
||||||
|
action.Animates(emptyGo.transform, "m_LocalScale.z").WithFrameCountUnit(unit =>
|
||||||
|
{
|
||||||
|
unit.Constant(0, 0);
|
||||||
|
unit.Constant(seconds, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Object.DestroyImmediate(emptyGo);
|
||||||
|
return clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SkinnedMeshRenderer> FindWithBlendshape(AvatarAssets assets, string shapeName)
|
||||||
|
{
|
||||||
|
var list = new List<SkinnedMeshRenderer>();
|
||||||
|
foreach (var smr in assets.root.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
||||||
|
{
|
||||||
|
var mesh = smr.sharedMesh;
|
||||||
|
if (!mesh) continue;
|
||||||
|
|
||||||
|
int count = mesh.blendShapeCount;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (mesh.GetBlendShapeName(i) == shapeName)
|
||||||
|
{
|
||||||
|
list.Add(smr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<T> FindNamedComponents<T>(Transform parent, string name) where T : Component
|
||||||
|
{
|
||||||
|
var list = new List<T>();
|
||||||
|
foreach (var component in parent.GetComponentsInChildren<T>(true))
|
||||||
|
{
|
||||||
|
if (component.gameObject.name == name)
|
||||||
|
{
|
||||||
|
list.Add(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnityEngine.Debug.Log($"Found {list.Count} {name} components");
|
||||||
|
foreach (var component in list)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log($"Component: {component.gameObject.name}");
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<T> FindNamedComponents<T>(AvatarAssets assets, string name) where T : Component
|
||||||
|
{
|
||||||
|
return FindNamedComponents<T>(assets.root.transform, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class AvatarBootstrapCore
|
||||||
|
{
|
||||||
|
|
||||||
|
private static AnimatorController GetController(AvatarDefinition definition)
|
||||||
|
{
|
||||||
|
string metaPath = definition.FXLayerPath + ".meta";
|
||||||
|
string originalGuid = null;
|
||||||
|
if (System.IO.File.Exists(metaPath))
|
||||||
|
{
|
||||||
|
foreach (var line in System.IO.File.ReadAllLines(metaPath))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("guid: "))
|
||||||
|
{
|
||||||
|
originalGuid = line.Substring(6).Trim();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AssetDatabase.LoadAssetAtPath<AnimatorController>(definition.FXLayerPath) != null)
|
||||||
|
{
|
||||||
|
AssetDatabase.DeleteAsset(definition.FXLayerPath);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
var newController = AnimatorController.CreateAnimatorControllerAtPath(definition.FXLayerPath);
|
||||||
|
if (originalGuid != null && System.IO.File.Exists(metaPath))
|
||||||
|
{
|
||||||
|
var lines = System.IO.File.ReadAllLines(metaPath);
|
||||||
|
for (int i = 0; i < lines.Length; ++i)
|
||||||
|
{
|
||||||
|
if (lines[i].StartsWith("guid: "))
|
||||||
|
{
|
||||||
|
lines[i] = "guid: " + originalGuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.IO.File.WriteAllLines(metaPath, lines);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
return AssetDatabase.LoadAssetAtPath<AnimatorController>(definition.FXLayerPath);
|
||||||
|
}
|
||||||
|
public static void RunForCurrentAvatar(AvatarDefinition definition)
|
||||||
|
{
|
||||||
|
|
||||||
|
var allLayerGroups = LayerGroup.Instances.ToList();
|
||||||
|
var layerGroups = allLayerGroups
|
||||||
|
.Where(lg => lg.TargetDefinitions.Contains(definition))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Start overall timer
|
||||||
|
var overallStopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
AvatarLogger.LogInfo("Starting SoldAvatarBootstrap generation for definition: " + definition.DisplayName);
|
||||||
|
GameObject root = null;
|
||||||
|
foreach (var candidate in GameObject.FindObjectsOfType<VRCAvatarDescriptor>(true))
|
||||||
|
{
|
||||||
|
if (definition.IsApplicable(candidate.gameObject))
|
||||||
|
{
|
||||||
|
AvatarLogger.LogInfo($"Found suitable avatar: {candidate.gameObject.name}");
|
||||||
|
root = candidate.gameObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogError($"No suitable avatar found for definition: {definition.DisplayName}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if the root GameObject or the component itself is disabled
|
||||||
|
if (!root.activeSelf || !root.gameObject.activeInHierarchy)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogWarning($"Avatar root '{root.name}' is disabled or inactive. Skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarAssets assets = new();
|
||||||
|
assets.root = root;
|
||||||
|
|
||||||
|
assets.isPC = EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows
|
||||||
|
|| EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Time AAC initialization
|
||||||
|
var initStopwatch = Stopwatch.StartNew();
|
||||||
|
AvatarLogger.LogInfo("Initializing Animator As Code...");
|
||||||
|
assets.aac = AacV1.Create(new AacConfiguration
|
||||||
|
{
|
||||||
|
SystemName = definition.SystemName,
|
||||||
|
AnimatorRoot = root.transform,
|
||||||
|
DefaultValueRoot = root.transform,
|
||||||
|
AssetKey = GUID.Generate().ToString(),
|
||||||
|
AssetContainer = GetController(definition),
|
||||||
|
ContainerMode = AacConfiguration.Container.Everything,
|
||||||
|
DefaultsProvider = new AacDefaultsProvider(true)
|
||||||
|
});
|
||||||
|
assets.emptyClip = assets.aac.NewClip();
|
||||||
|
|
||||||
|
assets.fx = assets.aac.NewAnimatorController();
|
||||||
|
initStopwatch.Stop();
|
||||||
|
AvatarLogger.LogInfo($"AAC initialization completed in {initStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
// Process layer groups with individual timing
|
||||||
|
// Filter out the template LayerGroup (by SystemName)
|
||||||
|
// AACLogger.LogInfo($"Processing {layerGroups.Count} layer groups...");
|
||||||
|
|
||||||
|
AvatarLogger.LogInfo($"Processing {layerGroups.Count} layer groups...");
|
||||||
|
var totalLayerGroupTime = 0L;
|
||||||
|
var processedCount = 0;
|
||||||
|
var skippedCount = 0;
|
||||||
|
|
||||||
|
foreach (var layerGroup in layerGroups)
|
||||||
|
{
|
||||||
|
var layerStopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
bool skipped = false;
|
||||||
|
|
||||||
|
if (!layerGroup.enabled)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (disabled)");
|
||||||
|
skipped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipped)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogInfo($"Running layer group: {layerGroup.DisplayName}");
|
||||||
|
layerGroup.Run(assets);
|
||||||
|
processedCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skippedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
layerStopwatch.Stop();
|
||||||
|
totalLayerGroupTime += layerStopwatch.ElapsedMilliseconds;
|
||||||
|
AvatarLogger.LogInfo($"Layer group '{layerGroup.DisplayName}' completed in {layerStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final timing summary
|
||||||
|
overallStopwatch.Stop();
|
||||||
|
AvatarLogger.LogSuccess($"SoldAvatarBootstrap generation completed successfully!");
|
||||||
|
AvatarLogger.LogInfo($"=== TIMING SUMMARY ===");
|
||||||
|
AvatarLogger.LogInfo($"Total time: {overallStopwatch.ElapsedMilliseconds}ms ({overallStopwatch.Elapsed.TotalSeconds:F2}s)");
|
||||||
|
AvatarLogger.LogInfo($"AAC initialization: {initStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
AvatarLogger.LogInfo($"Layer groups: {totalLayerGroupTime}ms (processed: {processedCount}, skipped: {skippedCount})");
|
||||||
|
AvatarLogger.LogInfo($"Average per layer group: {(processedCount > 0 ? totalLayerGroupTime / processedCount : 0)}ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Editor/Core.cs.meta
Normal file
11
Editor/Core.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 646700d2b124c3e4daf4532e7046f849
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
20
Editor/Definition.cs
Normal file
20
Editor/Definition.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap
|
||||||
|
{
|
||||||
|
public abstract class AvatarDefinition
|
||||||
|
{
|
||||||
|
private static readonly List<AvatarDefinition> instances = new();
|
||||||
|
|
||||||
|
protected AvatarDefinition() => instances.Add(this);
|
||||||
|
|
||||||
|
public static IEnumerable<AvatarDefinition> Instances => instances;
|
||||||
|
|
||||||
|
public abstract string DisplayName { get; }
|
||||||
|
public abstract string SystemName { get; }
|
||||||
|
public abstract string FXLayerPath { get; }
|
||||||
|
|
||||||
|
public abstract bool IsApplicable(GameObject avatarRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Editor/Definition.cs.meta
Normal file
11
Editor/Definition.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 04c641dd53bc5ac49b4e0c1cabab4a63
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
24
Editor/LayerGroup.cs
Normal file
24
Editor/LayerGroup.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap
|
||||||
|
{
|
||||||
|
public abstract class LayerGroup
|
||||||
|
{
|
||||||
|
public virtual bool enabled { get { return true; } }
|
||||||
|
private AvatarLayerGroupLogger _logger;
|
||||||
|
|
||||||
|
protected AvatarLayerGroupLogger Logger => _logger ??= new AvatarLayerGroupLogger(SystemName);
|
||||||
|
|
||||||
|
private static readonly List<LayerGroup> instances = new();
|
||||||
|
|
||||||
|
protected LayerGroup() => instances.Add(this);
|
||||||
|
|
||||||
|
public static IEnumerable<LayerGroup> Instances => instances;
|
||||||
|
|
||||||
|
public abstract string DisplayName { get; }
|
||||||
|
public abstract string SystemName { get; }
|
||||||
|
public abstract AvatarDefinition[] TargetDefinitions { get; }
|
||||||
|
|
||||||
|
public abstract void Run(AvatarAssets assets);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Editor/LayerGroup.cs.meta
Normal file
11
Editor/LayerGroup.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4fcc5c3f7007f9244aebe2f88702d429
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
92
Editor/Logger.cs
Normal file
92
Editor/Logger.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap
|
||||||
|
{
|
||||||
|
public static class AvatarLogger
|
||||||
|
{
|
||||||
|
private const string Prefix = "[SoldAvatarBootstrap]";
|
||||||
|
|
||||||
|
public static bool EnableDebug { get; set; } = false;
|
||||||
|
|
||||||
|
public static void Log(string message)
|
||||||
|
{
|
||||||
|
Debug.Log(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogDebug(string message)
|
||||||
|
{
|
||||||
|
if (!EnableDebug) return;
|
||||||
|
Debug.Log(Format("DEBUG: " + message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogInfo(string message)
|
||||||
|
{
|
||||||
|
Debug.Log(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogWarning(string message)
|
||||||
|
{
|
||||||
|
Debug.LogWarning(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogError(string message)
|
||||||
|
{
|
||||||
|
Debug.LogError(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogSuccess(string message)
|
||||||
|
{
|
||||||
|
Debug.Log(Format("✅ " + message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Format(string message)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(message) ? Prefix : $"{Prefix} {message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AvatarLayerGroupLogger
|
||||||
|
{
|
||||||
|
private readonly string _groupName;
|
||||||
|
|
||||||
|
public AvatarLayerGroupLogger(string groupName)
|
||||||
|
{
|
||||||
|
_groupName = groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.Log(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogDebug(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogDebug(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInfo(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogInfo(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogWarning(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogWarning(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogError(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogError(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogSuccess(string message)
|
||||||
|
{
|
||||||
|
AvatarLogger.LogSuccess(Format(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Format(string message)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(message) ? $"[{_groupName}]" : $"[{_groupName}] {message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Editor/Logger.cs.meta
Normal file
11
Editor/Logger.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ad5c99a61550aa4cbf010a7d834cb67
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
21
Editor/SoldAvatarBootstrap.Editor.asmdef
Normal file
21
Editor/SoldAvatarBootstrap.Editor.asmdef
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "SoldAvatarBootstrap.Editor",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:5718fb738711cd34ea54e9553040911d",
|
||||||
|
"GUID:b906909fcc54f634db50f2cad0f988d9",
|
||||||
|
"GUID:d689052aa981bf8459346a530f6e6678",
|
||||||
|
"GUID:71d9dcc7d30ab1c45866d01afa59b6cf"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
7
Editor/SoldAvatarBootstrap.Editor.asmdef.meta
Normal file
7
Editor/SoldAvatarBootstrap.Editor.asmdef.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 16dfbe6f38dd98d4aa89b7eaac50e6c8
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
7
LICENSE.meta
Normal file
7
LICENSE.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 545c229b037e15745b164b1dbcc4f885
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
7
README.md.meta
Normal file
7
README.md.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e1d829a80fa35844abdc4eb785823b8d
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Template.meta
Normal file
8
Template.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bd7f5cd94d343094780005eb00d6c66e
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
30
Template/Definition.cs
Normal file
30
Template/Definition.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap.Template
|
||||||
|
{
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public class TemplateDefinition : AvatarDefinition
|
||||||
|
{
|
||||||
|
public static readonly TemplateDefinition Instance = new();
|
||||||
|
|
||||||
|
static TemplateDefinition() { }
|
||||||
|
|
||||||
|
public override string DisplayName => "Template";
|
||||||
|
|
||||||
|
public override string SystemName => "template";
|
||||||
|
|
||||||
|
public override string FXLayerPath => "Assets/_LillithRosePup/SoldAvatarBootstrap/Template/FX.controller";
|
||||||
|
|
||||||
|
public override bool IsApplicable(GameObject avatarRoot)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("LillithRosePup/SoldAvatarBootstrap/Template")]
|
||||||
|
public static void Generate()
|
||||||
|
{
|
||||||
|
AvatarBootstrapCore.RunForCurrentAvatar(Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Template/Definition.cs.meta
Normal file
11
Template/Definition.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ea2d4a8738a3e0449830521d9f2ab669
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
21
Template/Layer.cs
Normal file
21
Template/Layer.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace gay.lilyy.SoldAvatarBootstrap.Template
|
||||||
|
{
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public class TemplateLayer : LayerGroup
|
||||||
|
{
|
||||||
|
private static readonly TemplateLayer _instance = new();
|
||||||
|
|
||||||
|
static TemplateLayer() { }
|
||||||
|
|
||||||
|
public override string DisplayName => "Template";
|
||||||
|
|
||||||
|
public override string SystemName => "template";
|
||||||
|
public override AvatarDefinition[] TargetDefinitions => new[] { TemplateDefinition.Instance };
|
||||||
|
public override void Run(AvatarAssets assets)
|
||||||
|
{
|
||||||
|
Logger.LogInfo("LayerGroup Template.Run() Called!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Template/Layer.cs.meta
Normal file
11
Template/Layer.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8250cbd1c8378ab4592627fb1eb4b70d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
18
Template/Template.asmdef
Normal file
18
Template/Template.asmdef
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "Template",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:16dfbe6f38dd98d4aa89b7eaac50e6c8"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
7
Template/Template.asmdef.meta
Normal file
7
Template/Template.asmdef.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ab920be56a4be1049a14744810032574
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Loading…
Add table
Add a link
Reference in a new issue