using UnityEditor;
using UnityEngine;
using AnimatorAsCode.V1;
using System.Collections.Generic;
using gay.lilyy.aaccore;
using gay.lilyy.aacshared.runtimecomponents;
using gay.lilyy.Common;
namespace gay.lilyy.aacshared.layers
{
/**
ported from v5
*/
[InitializeOnLoad]
public class LanternFlicker : LayerGroup
{
private static readonly LanternFlicker _instance = new();
static LanternFlicker() { }
public override string DisplayName => "Lantern Flicker";
public override string SystemName => "lantern_flicker";
public override bool shouldWarnIfNotApplicable => false;
private Transform GetLantern(AACAssets assets)
{
return AACUtils.FindChildRecursive(assets.ctx.AvatarRootTransform, "Lantern Floater");
}
public override bool IsApplicable(AACAssets assets)
{
var definition = ComponentHelper.GetComponentInChildrenWithError(assets.ctx.AvatarRootObject);
if (definition == null) return false;
if (!definition.enabled) return false;
var lamp = GetLantern(assets);
if (lamp == null)
{
Logger.LogWarning("Lamp Light could not be found!");
return false;
}
var light = lamp.GetComponentInChildren();
return light != null;
}
private void CreateFlickerLayer(AACAssets assets)
{
var lamp = GetLantern(assets);
var light = lamp.GetComponentInChildren();
var layer = assets.fx.NewLayer("Lantern Flicker");
var flickerParam = layer.BoolParameter("LanternFlicker");
var off = layer.NewState("Off").WithAnimation(
assets.aac.NewClip().Animating(anim =>
{
if (light != null) {
anim.Animates(light, "m_Enabled").WithFrameCountUnit(sec =>
{
sec.Constant(0, 0);
});
anim.Animates(light, "m_Intensity").WithFrameCountUnit(sec =>
{
sec.Constant(0, light.intensity);
});
}
})
);
layer.WithDefaultState(off);
var on = layer.NewState("Flicker").WithAnimation(
assets.aac.NewClip().Animating(anim =>
{
AnimateLantern(assets, anim, lamp);
}).Looping()
);
off.TransitionsTo(on).When(flickerParam.IsEqualTo(true));
on.TransitionsTo(off).When(flickerParam.IsEqualTo(false));
}
private void CreateBrightnessLayer(AACAssets assets)
{
var lamp = GetLantern(assets);
var light = lamp.GetComponentInChildren();
if (light == null) return;
var layer = assets.fx.NewLayer("Lantern Brightness");
var brightnessParam = layer.FloatParameter("LanternBrightness");
var state = layer.NewState("Brightness").WithAnimation(
assets.aac.NewClip().Animating(anim =>
{
anim.Animates(light, "m_Enabled").WithUnit(AacFlUnit.Frames, sec =>
{
sec.Linear(0, 0);
sec.Linear(1, 1);
});
anim.AnimatesColor(light, "m_Color").WithUnit(AacFlUnit.Frames, sec =>
{
sec.Linear(0, light.color * 0);
sec.Linear(100, light.color);
});
})
).WithMotionTime(brightnessParam);
}
private void AnimateLantern(AACAssets assets, AacFlEditClip anim, Transform lantern)
{
var renderer = lantern.GetComponent();
var light = lantern.GetComponentInChildren();
if (renderer == null)
{
Logger.LogWarning("AnimateLantern: Missing renderer on lantern");
return;
}
var rng = new System.Random("lillithlanternrandomseed".GetHashCode());
var keyframes = new List<(float time, double value)>();
float time = 0;
while (time < 60)
{
double value = rng.NextDouble();
keyframes.Add((time, value));
time += (float)(rng.NextDouble() * (0.3 - 0.05) + 0.05);
}
if (keyframes.Count == 0)
{
Logger.LogWarning("AnimateLantern: No keyframes generated");
}
if (light != null)
{
anim.Animates(light, "m_Intensity").WithSecondsUnit(sec =>
{
foreach (var (t, v) in keyframes)
{
sec.Easing(t, (float)v * light.intensity);
}
});
}
if (assets.isPC) {
Logger.LogInfo("Using PC material for lantern flicker");
Color initialColor = renderer.sharedMaterial.GetColor("_Emission_Color");
// ValueFactory Orbits
var prop = "material._Emission_Color";
void animateChannel(string suffix, float initial)
{
anim.Animates(renderer, $"{prop}.{suffix}").WithSecondsUnit(sec =>
{
foreach (var (t, v) in keyframes)
{
sec.Easing(t, initial * (float)v);
}
});
}
animateChannel("x", initialColor.r);
animateChannel("y", initialColor.g);
animateChannel("z", initialColor.b);
animateChannel("w", initialColor.a);
}
else
{
// Toon Standard
Logger.LogInfo("Using Non-PC material for lantern flicker");
// float initialStrength = renderer.sharedMaterial.GetFloat("_EmissionStrength");
// this still isnt running before vqt for some cursed reason so im just gonna hardcode this
var initialStrength = 2;
anim.Animates(renderer, "material._EmissionStrength").WithSecondsUnit(sec =>
{
foreach (var (t, v) in keyframes)
{
sec.Easing(t, initialStrength * (float)v);
}
});
}
}
public override void Run(AACAssets assets)
{
CreateFlickerLayer(assets);
CreateBrightnessLayer(assets);
}
}
}