122 lines
5.4 KiB
C#
122 lines
5.4 KiB
C#
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine.UIElements;
|
|
using VF.Builder;
|
|
using VF.Feature.Base;
|
|
using VF.Inspector;
|
|
using VF.Model.Feature;
|
|
using VRC.SDK3.Avatars.Components;
|
|
|
|
namespace VF.Feature {
|
|
|
|
public class BlinkingBuilder : FeatureBuilder<Blinking> {
|
|
/** Adding this feature to the build will disable blinking when the param is true */
|
|
[NoBuilder]
|
|
public class BlinkingPrevention : FeatureModel {
|
|
public VFABool param;
|
|
}
|
|
|
|
[FeatureBuilderAction(FeatureOrder.Blinking)]
|
|
public void Apply() {
|
|
if (!StateExists(model.state)) return;
|
|
|
|
var avatar = avatarObject.GetComponent<VRCAvatarDescriptor>();
|
|
avatar.customEyeLookSettings.eyelidType = VRCAvatarDescriptor.EyelidType.None;
|
|
|
|
var fx = GetFx();
|
|
var blinkTriggerSynced = fx.NewBool("BlinkTriggerSynced", synced: true);
|
|
|
|
// Generator
|
|
{
|
|
var blinkCounter = fx.NewInt("BlinkCounter");
|
|
var layer = fx.NewLayer("Blink - Generator");
|
|
var remote = layer.NewState("Remote Trap");
|
|
var entry = layer.NewState("Entry");
|
|
var idle = layer.NewState("Idle");
|
|
var subtract = layer.NewState("Subtract");
|
|
var trigger0 = layer.NewState("Trigger 0").Move(subtract, 1, 0);
|
|
var trigger1 = layer.NewState("Trigger 1").Move(trigger0, 1, 0);
|
|
var randomize = layer.NewState("Randomize").Move(idle, 1, 0);
|
|
|
|
remote.TransitionsTo(entry).When(fx.IsLocal().IsTrue());
|
|
entry.TransitionsTo(idle).When(fx.Always());
|
|
|
|
idle.TransitionsTo(trigger0).When(blinkCounter.IsLessThan(1).And(blinkTriggerSynced.IsTrue()));
|
|
trigger0.Drives(blinkTriggerSynced, false);
|
|
trigger0.TransitionsTo(randomize).When(fx.Always());
|
|
|
|
idle.TransitionsTo(trigger1).When(blinkCounter.IsLessThan(1).And(blinkTriggerSynced.IsFalse()));
|
|
trigger1.Drives(blinkTriggerSynced, true);
|
|
trigger1.TransitionsTo(randomize).When(fx.Always());
|
|
|
|
randomize.DrivesRandom(blinkCounter, 2, 10);
|
|
randomize.TransitionsTo(idle).When(fx.Always());
|
|
|
|
idle.TransitionsTo(subtract).WithTransitionDurationSeconds(1f).When(fx.Always());
|
|
subtract.DrivesDelta(blinkCounter, -1);
|
|
subtract.TransitionsTo(idle).When(fx.Always());
|
|
}
|
|
|
|
// Receiver / Animator
|
|
{
|
|
var blinkClip = LoadState("blink", model.state);
|
|
var blinkDuration = model.transitionTime >= 0 ? model.transitionTime : 0.07f;
|
|
var holdDuration = model.holdTime >= 0 ? model.holdTime : 0;
|
|
var layer = fx.NewLayer("Blink - Receiver");
|
|
var idle = layer.NewState("Idle");
|
|
var waitFalse = layer.NewState("Waiting (false)");
|
|
var waitTrue = layer.NewState("Waiting (true)").Move(waitFalse, 1, 0);
|
|
var checkActive = layer.NewState("Check Active").Move(waitFalse, 0, 1);
|
|
var blinkStart = layer.NewState("Blink Start").Move(checkActive, 1, 0);
|
|
var blink = layer.NewState("Blink").WithAnimation(blinkClip).Move(blinkStart, 1, 0);
|
|
|
|
idle.TransitionsTo(waitFalse).When(blinkTriggerSynced.IsFalse());
|
|
idle.TransitionsTo(waitTrue).When(blinkTriggerSynced.IsTrue());
|
|
waitFalse.TransitionsTo(checkActive).When(blinkTriggerSynced.IsTrue());
|
|
waitTrue.TransitionsTo(checkActive).When(blinkTriggerSynced.IsFalse());
|
|
|
|
foreach (var prevention in allFeaturesInRun.OfType<BlinkingPrevention>()) {
|
|
checkActive.TransitionsTo(idle).When(prevention.param.IsTrue());
|
|
}
|
|
checkActive.TransitionsTo(blinkStart).When(fx.Always());
|
|
blinkStart.TransitionsTo(blink).WithTransitionDurationSeconds(blinkDuration).When(fx.Always());
|
|
if (holdDuration > 0) {
|
|
var hold = layer.NewState("Hold").WithAnimation(blinkClip).Move(blink, 1, 0);
|
|
blink.TransitionsTo(hold).WithTransitionDurationSeconds(holdDuration).When(fx.Always());
|
|
hold.TransitionsTo(idle).WithTransitionDurationSeconds(blinkDuration).When(fx.Always());
|
|
} else {
|
|
blink.TransitionsTo(idle).WithTransitionDurationSeconds(blinkDuration).When(fx.Always());
|
|
}
|
|
}
|
|
}
|
|
|
|
public override string GetEditorTitle() {
|
|
return "Blink Controller";
|
|
}
|
|
|
|
public override VisualElement CreateEditor(SerializedProperty prop) {
|
|
var c = new VisualElement();
|
|
c.Add(VRCFuryEditorUtils.Info(
|
|
"This feature will manage eye-blinking for your avatar. Note this will disable 'Eyelid Type' on the VRC avatar descriptor."));
|
|
c.Add(VRCFuryEditorUtils.WrappedLabel("Blinking state:"));
|
|
c.Add(VRCFuryEditorUtils.Prop(prop.FindPropertyRelative("state")));
|
|
var adv = new Foldout {
|
|
text = "Advanced",
|
|
value = false
|
|
};
|
|
adv.Add(VRCFuryEditorUtils.Prop(prop.FindPropertyRelative("transitionTime"), "Transition Time (s)"));
|
|
adv.Add(VRCFuryEditorUtils.WrappedLabel("-1 will use VRCFury recommended value"));
|
|
adv.Add(VRCFuryEditorUtils.Prop(prop.FindPropertyRelative("holdTime"), "Hold Time (s)"));
|
|
adv.Add(VRCFuryEditorUtils.WrappedLabel("Time eyelids will remain closed, -1 will use VRCFury recommended value"));
|
|
c.Add(adv);
|
|
return c;
|
|
}
|
|
|
|
public override bool AvailableOnProps() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|