Skip to content

Commit c81d1e6

Browse files
committed
Prevent crash when expression menus, expression parameters, and the FX layer are null.
1 parent 388a451 commit c81d1e6

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed

Editor/FlareAvatarContext.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using nadena.dev.ndmf;
66
using Sucrose;
77
using Sucrose.Animation;
8+
using UnityEditor;
89
using UnityEditor.Animations;
910
using UnityEngine;
1011
using VRC.SDK3.Avatars.Components;
@@ -49,8 +50,32 @@ public SucroseContainer GetSucrose(BuildContext build)
4950
if (_container is not null)
5051
return _container;
5152

52-
var fx = build.AvatarDescriptor.baseAnimationLayers.First(l => l.type is VRCAvatarDescriptor.AnimLayerType.FX);
53-
_container = new SucroseContainer((fx.animatorController as AnimatorController)!);
53+
VRCAvatarDescriptor.CustomAnimLayer? fx = null;
54+
var layers = build.AvatarDescriptor.baseAnimationLayers;
55+
for (int i = 0; i < layers.Length; i++)
56+
{
57+
var layer = layers[i];
58+
if (layer.type is not VRCAvatarDescriptor.AnimLayerType.FX)
59+
continue;
60+
61+
layer.isDefault = false;
62+
if (!layer.animatorController)
63+
{
64+
var controller = new AnimatorController
65+
{
66+
name = "[Flare] FX"
67+
};
68+
AssetDatabase.AddObjectToAsset(controller, build.AssetContainer);
69+
layers[i].animatorController = controller;
70+
}
71+
fx = layers[i];
72+
break;
73+
}
74+
75+
if (fx is null)
76+
throw new InvalidOperationException("Cannot find FX layer");
77+
78+
_container = new SucroseContainer((fx.Value.animatorController as AnimatorController)!);
5479

5580
if (_container.LayerCount is 0)
5681
_container.NewLayer().WithName("Base Layer").WithWeight(1f);

Editor/Passes/MenuizationPass.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ protected override void Execute(BuildContext context)
2323
var descriptor = context.AvatarDescriptor;
2424
var expressions = descriptor.expressionsMenu;
2525

26+
// If for a reason we have no controls, don't generate any menus.
27+
if (flare.ControlContexts.Count == 0)
28+
return;
29+
30+
if (expressions == null)
31+
{
32+
expressions = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
33+
expressions.controls = new List<VRCExpressionsMenu.Control>(8);
34+
AssetDatabase.AddObjectToAsset(expressions, context.AssetContainer);
35+
descriptor.expressionsMenu = expressions;
36+
}
37+
2638
foreach (var ctx in flare.ControlContexts)
2739
{
2840
if (ctx.Control.Type is not ControlType.Menu)
@@ -105,10 +117,10 @@ private static void ShrinkAndNestFolderization(VRCExpressionsMenu menu, Object c
105117
if (control.type is VRCExpressionsMenu.Control.ControlType.SubMenu && control.subMenu != null)
106118
ShrinkAndNestFolderization(control.subMenu, container);
107119

108-
if (8 >= menu.controls.Count)
120+
if (VRCExpressionsMenu.MAX_CONTROLS >= menu.controls.Count)
109121
return;
110122

111-
while (menu.controls.Count > 8)
123+
while (menu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS)
112124
{
113125
var more = menu.controls.FirstOrDefault(
114126
c => c.type is VRCExpressionsMenu.Control.ControlType.SubMenu && c.name == _subId

Editor/Passes/ParameterGenerationPass.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected override void Execute(BuildContext context)
1717
var vrcParams = descriptor.expressionParameters;
1818

1919
// If persistent, copy to avoid messing with the original.
20-
if (!EditorUtility.IsPersistent(vrcParams))
20+
if (!EditorUtility.IsPersistent(vrcParams) || vrcParams == null)
2121
return;
2222

2323
var newParams = ScriptableObject.CreateInstance<VRCExpressionParameters>();

Editor/Passes/ParametrizationPass.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Linq;
33
using Flare.Models;
44
using nadena.dev.ndmf;
5+
using UnityEditor;
6+
using UnityEngine;
57
using VRC.SDK3.Avatars.ScriptableObjects;
68

79
namespace Flare.Editor.Passes
@@ -36,6 +38,14 @@ protected override void Execute(BuildContext context)
3638
};
3739
});
3840

41+
if (vrcParams == null)
42+
{
43+
vrcParams = ScriptableObject.CreateInstance<VRCExpressionParameters>();
44+
vrcParams.parameters = Array.Empty<VRCExpressionParameters.Parameter>();
45+
AssetDatabase.AddObjectToAsset(vrcParams, context.AssetContainer);
46+
descriptor.expressionParameters = vrcParams;
47+
}
48+
3949
vrcParams.parameters = vrcParams.parameters.Concat(flareParameters).ToArray();
4050
}
4151
}

0 commit comments

Comments
 (0)