Compare commits
2 commits
6031db6620
...
452faae79a
| Author | SHA1 | Date | |
|---|---|---|---|
| 452faae79a | |||
| 4809e7cfa0 |
17 changed files with 275 additions and 159 deletions
|
|
@ -164,18 +164,18 @@ namespace gay.lilyy.aaccore
|
||||||
// Start overall timer
|
// Start overall timer
|
||||||
var overallStopwatch = Stopwatch.StartNew();
|
var overallStopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
V5AACLogger.LogInfo("Starting Lillith V5 AAC generation...");
|
AACLogger.LogInfo("Starting AAC generation...");
|
||||||
var root = ComponentHelper.GetComponentInChildrenWithError<AACRoot>(ctx.AvatarRootObject);
|
var root = ComponentHelper.GetComponentInChildrenWithError<AACRoot>(ctx.AvatarRootObject);
|
||||||
if (root == null)
|
if (root == null)
|
||||||
{
|
{
|
||||||
V5AACLogger.LogInfo("No LillithV5AACRoot component found. Skipping.");
|
AACLogger.LogInfo("No AACRoot component found. Skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if the root GameObject or the component itself is disabled
|
// Skip if the root GameObject or the component itself is disabled
|
||||||
if (!root.enabled || !root.gameObject.activeInHierarchy)
|
if (!root.enabled || !root.gameObject.activeInHierarchy)
|
||||||
{
|
{
|
||||||
V5AACLogger.LogInfo($"LillithV5AACRoot on GameObject '{root.name}' is disabled or inactive. Skipping.");
|
AACLogger.LogInfo($"AACRoot on GameObject '{root.name}' is disabled or inactive. Skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ namespace gay.lilyy.aaccore
|
||||||
|
|
||||||
// Time AAC initialization
|
// Time AAC initialization
|
||||||
var initStopwatch = Stopwatch.StartNew();
|
var initStopwatch = Stopwatch.StartNew();
|
||||||
V5AACLogger.LogInfo("Initializing Animator As Code...");
|
AACLogger.LogInfo("Initializing Animator As Code...");
|
||||||
assets.aac = AacV1.Create(new AacConfiguration
|
assets.aac = AacV1.Create(new AacConfiguration
|
||||||
{
|
{
|
||||||
SystemName = SystemName,
|
SystemName = SystemName,
|
||||||
|
|
@ -209,11 +209,11 @@ namespace gay.lilyy.aaccore
|
||||||
|
|
||||||
assets.fx = assets.aac.NewAnimatorController();
|
assets.fx = assets.aac.NewAnimatorController();
|
||||||
initStopwatch.Stop();
|
initStopwatch.Stop();
|
||||||
V5AACLogger.LogInfo($"AAC initialization completed in {initStopwatch.ElapsedMilliseconds}ms");
|
AACLogger.LogInfo($"AAC initialization completed in {initStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
// Process layer groups with individual timing
|
// Process layer groups with individual timing
|
||||||
// Filter out the template LayerGroup (by SystemName)
|
// Filter out the template LayerGroup (by SystemName)
|
||||||
V5AACLogger.LogInfo($"Processing {layerGroups.Count} layer groups...");
|
AACLogger.LogInfo($"Processing {layerGroups.Count} layer groups...");
|
||||||
|
|
||||||
var totalLayerGroupTime = 0L;
|
var totalLayerGroupTime = 0L;
|
||||||
var processedCount = 0;
|
var processedCount = 0;
|
||||||
|
|
@ -236,25 +236,25 @@ namespace gay.lilyy.aaccore
|
||||||
|
|
||||||
if (!layerGroup.enabled)
|
if (!layerGroup.enabled)
|
||||||
{
|
{
|
||||||
V5AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (disabled)");
|
AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (disabled)");
|
||||||
skipped = true;
|
skipped = true;
|
||||||
}
|
}
|
||||||
else if (layerGroup.experimental && !assets.experimentalEnabled)
|
else if (layerGroup.experimental && !assets.experimentalEnabled)
|
||||||
{
|
{
|
||||||
V5AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (Experimental)");
|
AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (Experimental)");
|
||||||
skipped = true;
|
skipped = true;
|
||||||
}
|
}
|
||||||
else if (!layerGroup.IsApplicable(assets))
|
else if (!layerGroup.IsApplicable(assets))
|
||||||
{
|
{
|
||||||
if (layerGroup.shouldWarnIfNotApplicable)
|
if (layerGroup.shouldWarnIfNotApplicable)
|
||||||
V5AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (Not applicable)");
|
AACLogger.LogWarning($"Skipping layer group: {layerGroup.DisplayName} (Not applicable)");
|
||||||
|
|
||||||
skipped = true;
|
skipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipped)
|
if (!skipped)
|
||||||
{
|
{
|
||||||
V5AACLogger.LogInfo($"Running layer group: {layerGroup.DisplayName}");
|
AACLogger.LogInfo($"Running layer group: {layerGroup.DisplayName}");
|
||||||
layerGroup.Run(assets);
|
layerGroup.Run(assets);
|
||||||
processedCount++;
|
processedCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -265,26 +265,26 @@ namespace gay.lilyy.aaccore
|
||||||
|
|
||||||
layerStopwatch.Stop();
|
layerStopwatch.Stop();
|
||||||
totalLayerGroupTime += layerStopwatch.ElapsedMilliseconds;
|
totalLayerGroupTime += layerStopwatch.ElapsedMilliseconds;
|
||||||
V5AACLogger.LogInfo($"Layer group '{layerGroup.DisplayName}' completed in {layerStopwatch.ElapsedMilliseconds}ms");
|
AACLogger.LogInfo($"Layer group '{layerGroup.DisplayName}' completed in {layerStopwatch.ElapsedMilliseconds}ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time Modular Avatar setup
|
// Time Modular Avatar setup
|
||||||
var maStopwatch = Stopwatch.StartNew();
|
var maStopwatch = Stopwatch.StartNew();
|
||||||
V5AACLogger.LogInfo("Creating Modular Avatar merge animator...");
|
AACLogger.LogInfo("Creating Modular Avatar merge animator...");
|
||||||
|
|
||||||
assets.modularAvatar.NewMergeAnimator(assets.fx.AnimatorController, VRCAvatarDescriptor.AnimLayerType.FX);
|
assets.modularAvatar.NewMergeAnimator(assets.fx.AnimatorController, VRCAvatarDescriptor.AnimLayerType.FX);
|
||||||
maStopwatch.Stop();
|
maStopwatch.Stop();
|
||||||
V5AACLogger.LogInfo($"Modular Avatar setup completed in {maStopwatch.ElapsedMilliseconds}ms");
|
AACLogger.LogInfo($"Modular Avatar setup completed in {maStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
// Final timing summary
|
// Final timing summary
|
||||||
overallStopwatch.Stop();
|
overallStopwatch.Stop();
|
||||||
V5AACLogger.LogSuccess($"Lillith V5 AAC generation completed successfully!");
|
AACLogger.LogSuccess($"Lillith AAC generation completed successfully!");
|
||||||
V5AACLogger.LogInfo($"=== TIMING SUMMARY ===");
|
AACLogger.LogInfo($"=== TIMING SUMMARY ===");
|
||||||
V5AACLogger.LogInfo($"Total time: {overallStopwatch.ElapsedMilliseconds}ms ({overallStopwatch.Elapsed.TotalSeconds:F2}s)");
|
AACLogger.LogInfo($"Total time: {overallStopwatch.ElapsedMilliseconds}ms ({overallStopwatch.Elapsed.TotalSeconds:F2}s)");
|
||||||
V5AACLogger.LogInfo($"AAC initialization: {initStopwatch.ElapsedMilliseconds}ms");
|
AACLogger.LogInfo($"AAC initialization: {initStopwatch.ElapsedMilliseconds}ms");
|
||||||
V5AACLogger.LogInfo($"Layer groups: {totalLayerGroupTime}ms (processed: {processedCount}, skipped: {skippedCount})");
|
AACLogger.LogInfo($"Layer groups: {totalLayerGroupTime}ms (processed: {processedCount}, skipped: {skippedCount})");
|
||||||
V5AACLogger.LogInfo($"Modular Avatar: {maStopwatch.ElapsedMilliseconds}ms");
|
AACLogger.LogInfo($"Modular Avatar: {maStopwatch.ElapsedMilliseconds}ms");
|
||||||
V5AACLogger.LogInfo($"Average per layer group: {(processedCount > 0 ? totalLayerGroupTime / processedCount : 0)}ms");
|
AACLogger.LogInfo($"Average per layer group: {(processedCount > 0 ? totalLayerGroupTime / processedCount : 0)}ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ namespace gay.lilyy.aaccore {
|
||||||
{
|
{
|
||||||
public virtual bool enabled { get { return true; } }
|
public virtual bool enabled { get { return true; } }
|
||||||
public virtual bool experimental { get { return false; } }
|
public virtual bool experimental { get { return false; } }
|
||||||
private V5AACLayerGroupLogger _logger;
|
private AACLayerGroupLogger _logger;
|
||||||
|
|
||||||
|
|
||||||
protected V5AACLayerGroupLogger Logger => _logger ??= new V5AACLayerGroupLogger(SystemName);
|
protected AACLayerGroupLogger Logger => _logger ??= new AACLayerGroupLogger(SystemName);
|
||||||
|
|
||||||
private static readonly List<LayerGroup> instances = new();
|
private static readonly List<LayerGroup> instances = new();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ using gay.lilyy.logger;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace gay.lilyy.aaccore {
|
namespace gay.lilyy.aaccore {
|
||||||
public class V5AACLogger : BaseLogger
|
public class AACLogger : BaseLogger
|
||||||
{
|
{
|
||||||
private static V5AACLogger _instance;
|
private static AACLogger _instance;
|
||||||
public static V5AACLogger Instance => _instance ??= new V5AACLogger();
|
public static AACLogger Instance => _instance ??= new AACLogger();
|
||||||
|
|
||||||
protected override string SystemName => "AACCore";
|
protected override string SystemName => "AACCore";
|
||||||
|
|
||||||
|
|
@ -36,11 +36,11 @@ namespace gay.lilyy.aaccore {
|
||||||
public static void LogDebug(string message, Object context = null) => Instance.Debug(message, context);
|
public static void LogDebug(string message, Object context = null) => Instance.Debug(message, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class V5AACLayerGroupLogger : BaseLogger
|
public class AACLayerGroupLogger : BaseLogger
|
||||||
{
|
{
|
||||||
private readonly string _layerName;
|
private readonly string _layerName;
|
||||||
|
|
||||||
public V5AACLayerGroupLogger(string layerName)
|
public AACLayerGroupLogger(string layerName)
|
||||||
{
|
{
|
||||||
_layerName = layerName;
|
_layerName = layerName;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ namespace gay.lilyy.aaccore {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adding this to the avatar root will build the FX layer.
|
/// Adding this to the avatar root will build the FX layer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AddComponentMenu("LillithRosePup/AAC Root")]
|
||||||
public class AACRoot : MonoBehaviour, IEditorOnly {
|
public class AACRoot : MonoBehaviour, IEditorOnly {
|
||||||
public bool experimentalPlayMode = true;
|
public bool experimentalPlayMode = true;
|
||||||
public bool experimentalUpload = false;
|
public bool experimentalUpload = false;
|
||||||
|
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using gay.lilyy.PlaneCam;
|
|
||||||
|
|
||||||
namespace gay.lilyy.PlaneCam.Editor
|
|
||||||
{
|
|
||||||
[InitializeOnLoad]
|
|
||||||
public class PlaneCamEditor
|
|
||||||
{
|
|
||||||
static PlaneCamEditor()
|
|
||||||
{
|
|
||||||
EditorApplication.update += UpdatePlaneCams;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UpdatePlaneCams()
|
|
||||||
{
|
|
||||||
PlaneCam[] planeCams = Object.FindObjectsOfType<PlaneCam>(true);
|
|
||||||
|
|
||||||
foreach (PlaneCam planeCam in planeCams)
|
|
||||||
{
|
|
||||||
if (planeCam == null || planeCam.target == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Camera cam = planeCam.GetComponent<Camera>();
|
|
||||||
if (cam == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Get the bounds of the target plane
|
|
||||||
Bounds bounds = GetBounds(planeCam.target);
|
|
||||||
|
|
||||||
if (bounds.size.magnitude < 0.001f)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Get plane normal and center
|
|
||||||
Vector3 planeNormal = GetPlaneNormal(planeCam.target, planeCam.direction);
|
|
||||||
Vector3 planeCenter = bounds.center;
|
|
||||||
|
|
||||||
// Calculate the plane's dimensions in its local space
|
|
||||||
// Project bounds size onto the plane's local axes
|
|
||||||
Transform planeTransform = planeCam.target.transform;
|
|
||||||
Vector3 localSize = bounds.size;
|
|
||||||
|
|
||||||
// Find the two dimensions that define the plane (ignore the smallest dimension)
|
|
||||||
// This assumes the plane is flat, so one dimension should be very small
|
|
||||||
float minDim = Mathf.Min(localSize.x, localSize.y, localSize.z);
|
|
||||||
float maxDim = Mathf.Max(localSize.x, localSize.y, localSize.z);
|
|
||||||
float midDim = localSize.x + localSize.y + localSize.z - minDim - maxDim;
|
|
||||||
|
|
||||||
// Use the larger of the two plane dimensions to ensure it fills the square viewport
|
|
||||||
float planeSize = Mathf.Max(maxDim, midDim);
|
|
||||||
|
|
||||||
// Set aspect ratio to 1:1 for square viewport
|
|
||||||
cam.aspect = 1.0f;
|
|
||||||
|
|
||||||
// Calculate distance and position
|
|
||||||
if (cam.orthographic)
|
|
||||||
{
|
|
||||||
cam.orthographicSize = planeSize * 0.5f;
|
|
||||||
// Position camera perpendicular to the plane
|
|
||||||
cam.transform.position = planeCenter - planeNormal * 10f; // Distance doesn't matter for orthographic
|
|
||||||
cam.transform.LookAt(planeCenter, planeTransform.up);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For perspective camera, calculate distance based on FOV
|
|
||||||
// distance = (size/2) / tan(FOV/2)
|
|
||||||
float halfFOV = cam.fieldOfView * 0.5f * Mathf.Deg2Rad;
|
|
||||||
float distance = (planeSize * 0.5f) / Mathf.Tan(halfFOV);
|
|
||||||
|
|
||||||
// Position camera perpendicular to the plane, looking at center
|
|
||||||
cam.transform.position = planeCenter - planeNormal * distance;
|
|
||||||
cam.transform.LookAt(planeCenter, planeTransform.up);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bounds GetBounds(GameObject target)
|
|
||||||
{
|
|
||||||
Renderer renderer = target.GetComponent<Renderer>();
|
|
||||||
if (renderer != null)
|
|
||||||
{
|
|
||||||
return renderer.bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no renderer, try to get bounds from collider
|
|
||||||
Collider collider = target.GetComponent<Collider>();
|
|
||||||
if (collider != null)
|
|
||||||
{
|
|
||||||
return collider.bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: use transform scale
|
|
||||||
return new Bounds(target.transform.position, target.transform.lossyScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Vector3 GetPlaneNormal(GameObject target, PlaneDirection direction)
|
|
||||||
{
|
|
||||||
Transform t = target.transform;
|
|
||||||
|
|
||||||
// Use the specified direction setting
|
|
||||||
switch (direction)
|
|
||||||
{
|
|
||||||
case PlaneDirection.XPositive:
|
|
||||||
return t.right;
|
|
||||||
case PlaneDirection.XNegative:
|
|
||||||
return -t.right;
|
|
||||||
case PlaneDirection.YPositive:
|
|
||||||
return t.up;
|
|
||||||
case PlaneDirection.YNegative:
|
|
||||||
return -t.up;
|
|
||||||
case PlaneDirection.ZPositive:
|
|
||||||
return t.forward;
|
|
||||||
case PlaneDirection.ZNegative:
|
|
||||||
return -t.forward;
|
|
||||||
default:
|
|
||||||
return t.forward;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gay.lilyy.PlaneCam
|
namespace gay.lilyy.PlaneCam
|
||||||
{
|
{
|
||||||
|
|
@ -20,5 +22,124 @@ namespace gay.lilyy.PlaneCam
|
||||||
{
|
{
|
||||||
public GameObject target;
|
public GameObject target;
|
||||||
public PlaneDirection direction = PlaneDirection.ZPositive;
|
public PlaneDirection direction = PlaneDirection.ZPositive;
|
||||||
|
|
||||||
|
public void UpdateCamera()
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Camera cam = GetComponent<Camera>();
|
||||||
|
if (cam == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the bounds of the target plane
|
||||||
|
Bounds bounds = GetBounds(target);
|
||||||
|
|
||||||
|
if (bounds.size.magnitude < 0.001f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get plane normal and center
|
||||||
|
Vector3 planeNormal = GetPlaneNormal(target, direction);
|
||||||
|
Vector3 planeCenter = bounds.center;
|
||||||
|
|
||||||
|
// Calculate the plane's dimensions in its local space
|
||||||
|
// Project bounds size onto the plane's local axes
|
||||||
|
Transform planeTransform = target.transform;
|
||||||
|
Vector3 localSize = bounds.size;
|
||||||
|
|
||||||
|
// Find the two dimensions that define the plane (ignore the smallest dimension)
|
||||||
|
// This assumes the plane is flat, so one dimension should be very small
|
||||||
|
float minDim = Mathf.Min(localSize.x, localSize.y, localSize.z);
|
||||||
|
float maxDim = Mathf.Max(localSize.x, localSize.y, localSize.z);
|
||||||
|
float midDim = localSize.x + localSize.y + localSize.z - minDim - maxDim;
|
||||||
|
|
||||||
|
// Use the larger of the two plane dimensions to ensure it fills the square viewport
|
||||||
|
float planeSize = Mathf.Max(maxDim, midDim);
|
||||||
|
|
||||||
|
// Set aspect ratio to 1:1 for square viewport
|
||||||
|
cam.aspect = 1.0f;
|
||||||
|
|
||||||
|
// Calculate distance and position
|
||||||
|
if (cam.orthographic)
|
||||||
|
{
|
||||||
|
cam.orthographicSize = planeSize * 0.5f;
|
||||||
|
// Position camera perpendicular to the plane
|
||||||
|
cam.transform.position = planeCenter - planeNormal * 10f; // Distance doesn't matter for orthographic
|
||||||
|
cam.transform.LookAt(planeCenter, planeTransform.up);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For perspective camera, calculate distance based on FOV
|
||||||
|
// distance = (size/2) / tan(FOV/2)
|
||||||
|
float halfFOV = cam.fieldOfView * 0.5f * Mathf.Deg2Rad;
|
||||||
|
float distance = (planeSize * 0.5f) / Mathf.Tan(halfFOV);
|
||||||
|
|
||||||
|
// Position camera perpendicular to the plane, looking at center
|
||||||
|
cam.transform.position = planeCenter - planeNormal * distance;
|
||||||
|
cam.transform.LookAt(planeCenter, planeTransform.up);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bounds GetBounds(GameObject target)
|
||||||
|
{
|
||||||
|
Renderer renderer = target.GetComponent<Renderer>();
|
||||||
|
if (renderer != null)
|
||||||
|
{
|
||||||
|
return renderer.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no renderer, try to get bounds from collider
|
||||||
|
Collider collider = target.GetComponent<Collider>();
|
||||||
|
if (collider != null)
|
||||||
|
{
|
||||||
|
return collider.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: use transform scale
|
||||||
|
return new Bounds(target.transform.position, target.transform.lossyScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 GetPlaneNormal(GameObject target, PlaneDirection direction)
|
||||||
|
{
|
||||||
|
Transform t = target.transform;
|
||||||
|
|
||||||
|
// Use the specified direction setting
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case PlaneDirection.XPositive:
|
||||||
|
return t.right;
|
||||||
|
case PlaneDirection.XNegative:
|
||||||
|
return -t.right;
|
||||||
|
case PlaneDirection.YPositive:
|
||||||
|
return t.up;
|
||||||
|
case PlaneDirection.YNegative:
|
||||||
|
return -t.up;
|
||||||
|
case PlaneDirection.ZPositive:
|
||||||
|
return t.forward;
|
||||||
|
case PlaneDirection.ZNegative:
|
||||||
|
return -t.forward;
|
||||||
|
default:
|
||||||
|
return t.forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[CustomEditor(typeof(PlaneCam))]
|
||||||
|
public class PlaneCamInspector : Editor
|
||||||
|
{
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
|
||||||
|
PlaneCam planeCam = (PlaneCam)target;
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
if (GUILayout.Button("Update Camera"))
|
||||||
|
{
|
||||||
|
planeCam.UpdateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
8
PlatformSpecificFX.meta
Normal file
8
PlatformSpecificFX.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f2577c1118081964793d2e54370ea95d
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: dfb718cc85f807a4585cc3dd07098767
|
guid: 4fb4c374accfed2468cd020df25fe43c
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
22
PlatformSpecificFX/Editor/PlatformSpecificFXEditor.asmdef
Normal file
22
PlatformSpecificFX/Editor/PlatformSpecificFXEditor.asmdef
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "PlatformSpecificFXEditor",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:62ced99b048af7f4d8dfe4bed8373d76",
|
||||||
|
"GUID:5718fb738711cd34ea54e9553040911d",
|
||||||
|
"GUID:901e56b065a857d4483a77f8cae73588",
|
||||||
|
"GUID:209cbd2a789c4f72963fdbf1f8a01909",
|
||||||
|
"GUID:424958f3f014e9b43ab88ec66b389caf"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 0010e90dfaa354f4ca094b433acef847
|
guid: c8c6365cf8a2e724caa7fe8be7e75792
|
||||||
AssemblyDefinitionImporter:
|
AssemblyDefinitionImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
51
PlatformSpecificFX/Editor/PlatformSpecificFXPlugin.cs
Normal file
51
PlatformSpecificFX/Editor/PlatformSpecificFXPlugin.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using gay.lilyy.platformspecificfx;
|
||||||
|
using nadena.dev.ndmf;
|
||||||
|
using nadena.dev.ndmf.vrchat;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using VRC.SDK3.Avatars.Components;
|
||||||
|
|
||||||
|
[assembly: ExportsPlugin(typeof(PlatformSpecificFXPlugin))]
|
||||||
|
|
||||||
|
namespace gay.lilyy.platformspecificfx
|
||||||
|
{
|
||||||
|
public class PlatformSpecificFXPlugin : Plugin<PlatformSpecificFXPlugin>
|
||||||
|
{
|
||||||
|
public override string DisplayName => "Platform Specific FX";
|
||||||
|
public override string QualifiedName => "gay.lilyy.platformspecificfx";
|
||||||
|
|
||||||
|
protected override void Configure()
|
||||||
|
{
|
||||||
|
InPhase(BuildPhase.FirstChance).Run("PlatformSpecificFX", ctx =>
|
||||||
|
{
|
||||||
|
var configs = ctx.AvatarRootObject.GetComponentsInChildren<PlatformSpecificFX>(true);
|
||||||
|
if (configs == null || configs.Length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var targetAnimator = EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows
|
||||||
|
|| EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64 ?
|
||||||
|
configs[0].desktop : configs[0].mobile;
|
||||||
|
if (targetAnimator == null) throw new Exception("Target animator not found");
|
||||||
|
|
||||||
|
var baseAnimationLayers = ctx.VRChatAvatarDescriptor().baseAnimationLayers.ToList();
|
||||||
|
// replace the fx layer with the target animator
|
||||||
|
var foundFXLayer = false;
|
||||||
|
for (int i = 0; i < baseAnimationLayers.Count; i++)
|
||||||
|
{
|
||||||
|
var layer = baseAnimationLayers[i];
|
||||||
|
if (layer.type == VRCAvatarDescriptor.AnimLayerType.FX) {
|
||||||
|
Debug.Log($"Found FX Layer, Replacing with {targetAnimator.name}");
|
||||||
|
layer.animatorController = targetAnimator;
|
||||||
|
baseAnimationLayers[i] = layer;
|
||||||
|
foundFXLayer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundFXLayer) throw new Exception("FX Layer not found");
|
||||||
|
ctx.VRChatAvatarDescriptor().baseAnimationLayers = baseAnimationLayers.ToArray();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 0e148c194888c8f4b80fbb649b2f1a02
|
guid: 1ce53e373aea68e4b97c79e7e8df274c
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
8
PlatformSpecificFX/Runtime.meta
Normal file
8
PlatformSpecificFX/Runtime.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fb1855544ce8de94794ec16500fad59c
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
12
PlatformSpecificFX/Runtime/PlatformSpecificFX.cs
Normal file
12
PlatformSpecificFX/Runtime/PlatformSpecificFX.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace gay.lilyy.platformspecificfx
|
||||||
|
{
|
||||||
|
[AddComponentMenu("LillithRosePup/Platform Specific FX")]
|
||||||
|
public class PlatformSpecificFX : MonoBehaviour, VRC.SDKBase.IEditorOnly
|
||||||
|
{
|
||||||
|
public RuntimeAnimatorController desktop;
|
||||||
|
public RuntimeAnimatorController mobile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
11
PlatformSpecificFX/Runtime/PlatformSpecificFX.cs.meta
Normal file
11
PlatformSpecificFX/Runtime/PlatformSpecificFX.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 24bc2531ec6d029449c1cf0e322c6612
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "PlaneCamEditor",
|
"name": "PlatformSpecificFXRuntime",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [],
|
||||||
"GUID:a9f136790ce90f740a7142ab21ff971a"
|
"includePlatforms": [],
|
||||||
],
|
|
||||||
"includePlatforms": [
|
|
||||||
"Editor"
|
|
||||||
],
|
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
"overrideReferences": false,
|
"overrideReferences": false,
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 424958f3f014e9b43ab88ec66b389caf
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Loading…
Add table
Add a link
Reference in a new issue