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 b74791c956
commit 7cf7ff35b2
4 changed files with 83 additions and 32 deletions

View file

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

View file

@ -63,24 +63,32 @@ namespace HeavenStudio.Games.Loaders
}, },
new GameAction("arisa faceposer", "Idol Face Poser") 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, resizable = true,
defaultLength = 1, defaultLength = 1,
parameters = new List<Param>() parameters = new List<Param>()
{ {
new Param("poserOn", true, "Enable Face Poser", "Enables Face Poser on Arisa.", new List<Param.CollapseParam>() 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("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("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("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("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("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("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("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."), new Param("eyeEase", Util.EasingFunction.Ease.Instant, "Easing Type", "Set the type of easing for eye movement."),
} }
@ -687,15 +695,12 @@ namespace HeavenStudio.Games
} }
System.Threading.CancellationTokenSource mouthCancel = null; 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.ToggleFacePoser(enable);
arisaController.SetMouthShape(mouth); // eye control
if (enableEye)
{
arisaController.SetEyeShape(eyeL, eyeR); arisaController.SetEyeShape(eyeL, eyeR);
if (ease) if (ease)
{ {
@ -705,11 +710,23 @@ namespace HeavenStudio.Games
{ {
arisaController.SetEyeTarget(eyeX, eyeY); arisaController.SetEyeTarget(eyeX, eyeY);
} }
}
// mouth control
if (enableMouth)
{
if (mouthCancel != null)
{
mouthCancel.Cancel();
mouthCancel = null;
}
arisaController.SetMouthShape(mouth);
mouthCancel = BeatAction.New(instance, new List<BeatAction.Action>() mouthCancel = BeatAction.New(instance, new List<BeatAction.Action>()
{ {
new BeatAction.Action(beat + length, delegate { arisaController.SetMouthShape(mouthEnd);}), new BeatAction.Action(beat + length, delegate { arisaController.SetMouthShape(mouthEnd);}),
}); });
} }
}
const float HAIS_LENGTH = 4.5f; const float HAIS_LENGTH = 4.5f;
public void CallHai(double beat, bool noSound = false, bool noResponse = false, int type = 0) public void CallHai(double beat, bool noSound = false, bool noResponse = false, int type = 0)

View file

@ -133,7 +133,7 @@ namespace HeavenStudio.Editor
EventPropertyPrefab input = currentProperties[p.propertyName]; EventPropertyPrefab input = currentProperties[p.propertyName];
foreach (var c in p.collapseParams) 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.propertyCollapses.Add(new EventPropertyPrefab.PropertyCollapse(collapseables, c.CollapseOn, entity));
} }
input.SetCollapses(p.parameter); input.SetCollapses(p.parameter);

View file

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