recursive collapsing properties

tweaks to fan club face poser
separate mouth and eye controls
This commit is contained in:
minenice55 2024-05-12 17:37:01 -04:00
parent c330a54d1e
commit 94eeb1b0f9
4 changed files with 83 additions and 32 deletions

View file

@ -1219,9 +1219,6 @@ AnimatorStateTransition:
- m_ConditionMode: 6
m_ConditionEvent: Mouth Type
m_EventTreshold: 6
- m_ConditionMode: 4
m_ConditionEvent: Mouth Type
m_EventTreshold: 6
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 4795373212119028058}
m_Solo: 0
@ -1476,9 +1473,6 @@ AnimatorStateTransition:
- m_ConditionMode: 6
m_ConditionEvent: Mouth Type
m_EventTreshold: 0
- m_ConditionMode: 3
m_ConditionEvent: Mouth Type
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: -4363713536613775826}
m_Solo: 0

View file

@ -63,24 +63,32 @@ namespace HeavenStudio.Games.Loaders
},
new GameAction("arisa faceposer", "Idol Face Poser")
{
function = delegate { var e = eventCaller.currentEntity; FanClub.instance.SetArisaFacePoser(e["poserOn"], e["mouth"], e["mouthEnd"], e["eyeL"], e["eyeR"], e["eyex"], e["eyey"], e["eyeEaseEnable"], e.beat, e.length, e["eyeEase"]); },
function = delegate { var e = eventCaller.currentEntity; FanClub.instance.SetArisaFacePoser(e["poserOn"], e["mouthOn"], e["eyeOn"], e["mouth"], e["mouthEnd"], e["eyeL"], e["eyeR"], e["eyex"], e["eyey"], e["eyeEaseEnable"], e.beat, e.length, e["eyeEase"]); },
resizable = true,
defaultLength = 1,
parameters = new List<Param>()
{
new Param("poserOn", true, "Enable Face Poser", "Enables Face Poser on Arisa.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "mouth", "eyeL", "eyeR", "eyex", "eyey" }),
new Param.CollapseParam((x, _) => (bool)x, new string[] { "mouthOn", "eyeOn" }),
}),
new Param("mouthOn", true, "Enable Lip Sync Controls", "Enables Lip Sync controls.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, e) => (bool)x && (bool)e["poserOn"], new string[] { "mouth", "mouthEnd" }),
}),
new Param("mouth", FanClub.MouthShape.Normal, "Mouth Shape", "Sets mouth shape."),
new Param("mouthEnd", FanClub.MouthShape.Normal, "Last Mouth Shape", "Sets mouth shape at the end of the event."),
new Param("eyeOn", true, "Enable Eye Shaping", "Enables Eye Shaping controls.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, e) => (bool)x && (bool)e["poserOn"], new string[] { "eyeL", "eyeR", "eyex", "eyey", "eyeEaseEnable"}),
}),
new Param("eyeL", FanClub.EyeShape.Normal, "Left Eye Shape", "Sets left eye shape."),
new Param("eyeR", FanClub.EyeShape.Normal, "Right Eye Shape", "Sets right eye shape."),
new Param("eyex", new EntityTypes.Float(-1f, 1f, 0f), "Horizontal Eye Movement", "Sets horizontal eye movement."),
new Param("eyey", new EntityTypes.Float(-1f, 1f, 0f), "Vertical Eye Movement", "Sets vertical eye movement."),
new Param("eyeEaseEnable", true, "Ease Eye Movement", "Enable easing for eye movement.", new List<Param.CollapseParam>()
{
new Param.CollapseParam((x, _) => (bool)x, new string[] { "eyeEase" }),
new Param.CollapseParam((x, e) => (bool)x && (bool)e["poserOn"] && (bool)e["eyeOn"], new string[] { "eyeEase" }),
}),
new Param("eyeEase", Util.EasingFunction.Ease.Instant, "Easing Type", "Set the type of easing for eye movement."),
}
@ -687,28 +695,37 @@ namespace HeavenStudio.Games
}
System.Threading.CancellationTokenSource mouthCancel = null;
public void SetArisaFacePoser(bool enable, int mouth, int mouthEnd, int eyeL, int eyeR, float eyeX, float eyeY, bool ease, double beat, float length, int easeType)
public void SetArisaFacePoser(bool enable, bool enableMouth, bool enableEye, int mouth, int mouthEnd, int eyeL, int eyeR, float eyeX, float eyeY, bool ease, double beat, float length, int easeType)
{
if (mouthCancel != null)
{
mouthCancel.Cancel();
mouthCancel = null;
}
arisaController.ToggleFacePoser(enable);
arisaController.SetMouthShape(mouth);
arisaController.SetEyeShape(eyeL, eyeR);
if (ease)
// eye control
if (enableEye)
{
arisaController.SetEyeTargetEase(beat, length, eyeX, eyeY, (Util.EasingFunction.Ease)easeType);
arisaController.SetEyeShape(eyeL, eyeR);
if (ease)
{
arisaController.SetEyeTargetEase(beat, length, eyeX, eyeY, (Util.EasingFunction.Ease)easeType);
}
else
{
arisaController.SetEyeTarget(eyeX, eyeY);
}
}
else
// mouth control
if (enableMouth)
{
arisaController.SetEyeTarget(eyeX, eyeY);
if (mouthCancel != null)
{
mouthCancel.Cancel();
mouthCancel = null;
}
arisaController.SetMouthShape(mouth);
mouthCancel = BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { arisaController.SetMouthShape(mouthEnd);}),
});
}
mouthCancel = BeatAction.New(instance, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + length, delegate { arisaController.SetMouthShape(mouthEnd);}),
});
}
const float HAIS_LENGTH = 4.5f;

View file

@ -133,7 +133,7 @@ namespace HeavenStudio.Editor
EventPropertyPrefab input = currentProperties[p.propertyName];
foreach (var c in p.collapseParams)
{
List<GameObject> collapseables = c.collapseables.Select(x => currentProperties[x].gameObject).ToList();
List<EventPropertyPrefab> collapseables = c.collapseables.Select(x => currentProperties[x]).ToList();
input.propertyCollapses.Add(new EventPropertyPrefab.PropertyCollapse(collapseables, c.CollapseOn, entity));
}
input.SetCollapses(p.parameter);

View file

@ -32,25 +32,65 @@ namespace HeavenStudio.Editor
public void UpdateCollapse(object type)
{
List<EventPropertyPrefab> recursedCollapse = new() { this };
foreach (var p in propertyCollapses)
{
if (p.collapseables.Count > 0) { // there could be a better way to do it, but for now this works
foreach (var c in p.collapseables) {
if (c != null) c.SetActive(p.collapseOn(type, p.entity) && gameObject.activeSelf);
if (p.collapseables.Count > 0)
{
foreach (var c in p.collapseables)
{
if (c != null)
{
c.gameObject.SetActive(p.collapseOn(type, p.entity) && gameObject.activeSelf);
c.RecursiveUpdateCollapse(recursedCollapse);
}
}
} else {
}
else
{
_ = p.collapseOn(type, p.entity);
}
}
}
public void RecursiveUpdateCollapse(List<EventPropertyPrefab> updated)
{
if (updated == null)
{
updated = new();
}
if (updated.Contains(this))
{
return;
}
updated.Add(this);
foreach (var p in propertyCollapses)
{
if (p.collapseables.Count > 0)
{
foreach (var c in p.collapseables)
{
if (c != null)
{
c.gameObject.SetActive(p.collapseOn(entity[propertyName], p.entity) && gameObject.activeSelf);
c.RecursiveUpdateCollapse(updated);
}
}
}
else
{
_ = p.collapseOn(entity[propertyName], p.entity);
}
}
}
public class PropertyCollapse
{
public List<GameObject> collapseables;
public List<EventPropertyPrefab> collapseables;
public Func<object, RiqEntity, bool> collapseOn;
public RiqEntity entity;
public PropertyCollapse(List<GameObject> collapseables, Func<object, RiqEntity, bool> collapseOn, RiqEntity entity)
public PropertyCollapse(List<EventPropertyPrefab> collapseables, Func<object, RiqEntity, bool> collapseOn, RiqEntity entity)
{
this.collapseables = collapseables;
this.collapseOn = collapseOn;