Skip to content

Commit ad4de31

Browse files
[Rendering] Added skinned animation controller for skinned mesh animators;
[Editor] Fixed Guid being recreated each time a StapleAsset was saved;
1 parent b57d534 commit ad4de31

File tree

9 files changed

+538
-130
lines changed

9 files changed

+538
-130
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Staple;
5+
6+
public class SkinnedAnimationController
7+
{
8+
internal class Parameter
9+
{
10+
public SkinnedAnimationStateMachine.AnimationParameterType type;
11+
public bool boolValue;
12+
public int intValue;
13+
public float floatValue;
14+
}
15+
16+
internal SkinnedMeshAnimator animator;
17+
internal SkinnedAnimationStateMachine stateMachine;
18+
internal SkinnedAnimationStateMachine.AnimationState currentState;
19+
20+
private Dictionary<string, Parameter> parameters = new();
21+
22+
public SkinnedAnimationController(SkinnedMeshAnimator animator, SkinnedAnimationStateMachine stateMachine)
23+
{
24+
this.animator = animator;
25+
this.stateMachine = stateMachine;
26+
27+
var startState = this.stateMachine.states.FirstOrDefault()?.name;
28+
29+
if(startState != null)
30+
{
31+
SetState(startState);
32+
}
33+
34+
foreach (var parameter in stateMachine.parameters)
35+
{
36+
if(parameter.name == null || parameter.name.Length == 0)
37+
{
38+
continue;
39+
}
40+
41+
parameters.AddOrSetKey(parameter.name, new()
42+
{
43+
type = parameter.parameterType,
44+
});
45+
}
46+
}
47+
48+
public void SetBoolParameter(string name, bool value)
49+
{
50+
if(parameters.TryGetValue(name, out var parameter) &&
51+
parameter.type == SkinnedAnimationStateMachine.AnimationParameterType.Bool)
52+
{
53+
parameter.boolValue = value;
54+
}
55+
56+
CheckConditions();
57+
}
58+
59+
public void SetIntParameter(string name, int value)
60+
{
61+
if (parameters.TryGetValue(name, out var parameter) &&
62+
parameter.type == SkinnedAnimationStateMachine.AnimationParameterType.Int)
63+
{
64+
parameter.intValue = value;
65+
}
66+
67+
CheckConditions();
68+
}
69+
70+
public void SetFloatParameter(string name, float value)
71+
{
72+
if (parameters.TryGetValue(name, out var parameter) &&
73+
parameter.type == SkinnedAnimationStateMachine.AnimationParameterType.Float)
74+
{
75+
parameter.floatValue = value;
76+
}
77+
78+
CheckConditions();
79+
}
80+
81+
private bool CheckParameter(SkinnedAnimationStateMachine.AnimationConditionParameter parameter)
82+
{
83+
if (parameter.name == null || parameter.name.Length == 0)
84+
{
85+
return false;
86+
}
87+
88+
if (parameters.TryGetValue(parameter.name, out var localParameter))
89+
{
90+
var valid = false;
91+
92+
switch (parameter.condition)
93+
{
94+
case SkinnedAnimationStateMachine.AnimationCondition.Equal:
95+
96+
switch (localParameter.type)
97+
{
98+
case SkinnedAnimationStateMachine.AnimationParameterType.Bool:
99+
100+
valid = localParameter.boolValue == parameter.boolValue;
101+
102+
break;
103+
104+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
105+
106+
valid = localParameter.floatValue == parameter.floatValue;
107+
108+
break;
109+
110+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
111+
112+
valid = localParameter.intValue == parameter.intValue;
113+
114+
break;
115+
}
116+
117+
break;
118+
119+
case SkinnedAnimationStateMachine.AnimationCondition.NotEqual:
120+
121+
switch (localParameter.type)
122+
{
123+
case SkinnedAnimationStateMachine.AnimationParameterType.Bool:
124+
125+
valid = localParameter.boolValue != parameter.boolValue;
126+
127+
break;
128+
129+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
130+
131+
valid = localParameter.floatValue != parameter.floatValue;
132+
133+
break;
134+
135+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
136+
137+
valid = localParameter.intValue != parameter.intValue;
138+
139+
break;
140+
}
141+
142+
break;
143+
144+
case SkinnedAnimationStateMachine.AnimationCondition.Bigger:
145+
146+
switch (localParameter.type)
147+
{
148+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
149+
150+
valid = localParameter.floatValue > parameter.floatValue;
151+
152+
break;
153+
154+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
155+
156+
valid = localParameter.intValue > parameter.intValue;
157+
158+
break;
159+
}
160+
161+
break;
162+
163+
case SkinnedAnimationStateMachine.AnimationCondition.BiggerEqual:
164+
165+
switch (localParameter.type)
166+
{
167+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
168+
169+
valid = localParameter.floatValue >= parameter.floatValue;
170+
171+
break;
172+
173+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
174+
175+
valid = localParameter.intValue >= parameter.intValue;
176+
177+
break;
178+
}
179+
180+
break;
181+
182+
case SkinnedAnimationStateMachine.AnimationCondition.Less:
183+
184+
switch (localParameter.type)
185+
{
186+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
187+
188+
valid = localParameter.floatValue < parameter.floatValue;
189+
190+
break;
191+
192+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
193+
194+
valid = localParameter.intValue < parameter.intValue;
195+
196+
break;
197+
}
198+
199+
break;
200+
201+
case SkinnedAnimationStateMachine.AnimationCondition.LessEqual:
202+
203+
switch (localParameter.type)
204+
{
205+
case SkinnedAnimationStateMachine.AnimationParameterType.Float:
206+
207+
valid = localParameter.floatValue <= parameter.floatValue;
208+
209+
break;
210+
211+
case SkinnedAnimationStateMachine.AnimationParameterType.Int:
212+
213+
valid = localParameter.intValue <= parameter.intValue;
214+
215+
break;
216+
}
217+
218+
break;
219+
}
220+
221+
return valid;
222+
}
223+
224+
return false;
225+
}
226+
227+
private void CheckConditions()
228+
{
229+
if(currentState == null || currentState.connections.Count == 0)
230+
{
231+
return;
232+
}
233+
234+
foreach(var connection in currentState.connections)
235+
{
236+
var shouldTrigger = false;
237+
238+
if(connection.any)
239+
{
240+
foreach(var parameter in connection.parameters)
241+
{
242+
if(CheckParameter(parameter))
243+
{
244+
shouldTrigger = true;
245+
246+
break;
247+
}
248+
}
249+
}
250+
else
251+
{
252+
shouldTrigger = true;
253+
254+
foreach(var parameter in connection.parameters)
255+
{
256+
if(CheckParameter(parameter) == false)
257+
{
258+
shouldTrigger = false;
259+
260+
break;
261+
}
262+
}
263+
}
264+
265+
if(shouldTrigger)
266+
{
267+
SetState(connection.name);
268+
269+
break;
270+
}
271+
}
272+
}
273+
274+
private void SetState(string name)
275+
{
276+
if (name == null)
277+
{
278+
return;
279+
}
280+
281+
var state = animator.stateMachine.states.FirstOrDefault(x => x.name == name);
282+
283+
if (state == null)
284+
{
285+
return;
286+
}
287+
288+
currentState = state;
289+
290+
animator.repeat = state.repeat;
291+
animator.animation = state.animation;
292+
animator.playTime = 0;
293+
animator.evaluator = null;
294+
}
295+
}

Engine/Core/Rendering/Animation/AnimationStateMachine.cs renamed to Engine/Core/Rendering/Animation/SkinnedAnimationStateMachine.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Staple;
55

6-
public class AnimationStateMachine : IStapleAsset, IGuidAsset
6+
public class SkinnedAnimationStateMachine : IStapleAsset, IGuidAsset
77
{
88
public enum AnimationCondition
99
{
@@ -22,36 +22,52 @@ public enum AnimationParameterType
2222
Float,
2323
}
2424

25+
[Serializable]
26+
public class AnimationParameter
27+
{
28+
public string name;
29+
public AnimationParameterType parameterType;
30+
}
31+
2532
[Serializable]
2633
public class AnimationConditionParameter
2734
{
2835
public string name;
2936
public AnimationCondition condition;
30-
public AnimationParameterType parameterType;
3137
public bool boolValue;
3238
public int intValue;
3339
public float floatValue;
3440
}
3541

42+
[Serializable]
43+
public class AnimationStateConnection
44+
{
45+
public string name;
46+
public bool any;
47+
public bool onFinish;
48+
public List<AnimationConditionParameter> parameters = new();
49+
}
50+
3651
[Serializable]
3752
public class AnimationState
3853
{
3954
public string name;
40-
public string next;
4155
public string animation;
4256
public bool repeat;
43-
public bool any;
44-
public List<AnimationConditionParameter> parameters = new();
57+
58+
public List<AnimationStateConnection> connections = new();
4559
}
4660

4761
public Mesh mesh;
4862

4963
public List<AnimationState> states = new();
5064

65+
public List<AnimationParameter> parameters = new();
66+
5167
public string Guid { get; set; }
5268

5369
public static object Create(string guid)
5470
{
55-
return Resources.Load<AnimationStateMachine>(guid);
71+
return Resources.Load<SkinnedAnimationStateMachine>(guid);
5672
}
5773
}

Engine/Core/Rendering/Animation/SkinnedMeshAnimator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ internal class Item
1414
public string animation;
1515
public bool repeat = true;
1616

17-
public AnimationStateMachine stateMachine;
17+
public SkinnedAnimationStateMachine stateMachine;
18+
public SkinnedAnimationController animationController;
1819

1920
internal bool playInEditMode;
2021
internal float playTime;
2122
internal Dictionary<string, Item> nodeRenderers = new();
2223
internal SkinnedMeshAnimationEvaluator evaluator;
23-
internal AnimationStateMachine.AnimationState currentState;
2424
}

0 commit comments

Comments
 (0)