|
@@ -19,12 +19,20 @@ typedef AnimInfo = {
|
|
|
@:access(hrt.animgraph.BlendSpace2D)
|
|
|
class BlendSpace2D extends AnimNode {
|
|
|
@:input var bsX(default, set): Float = 0.5;
|
|
|
+ var realX : Float = 0.5;
|
|
|
+ var vX : Float = 0.0;
|
|
|
+
|
|
|
@:input var bsY(default, set): Float = 0.5;
|
|
|
+ var realY : Float = 0.5;
|
|
|
+ var vY : Float = 0.0;
|
|
|
+
|
|
|
|
|
|
@:s var path : String = "";
|
|
|
|
|
|
var dirtyPos: Bool = true;
|
|
|
|
|
|
+ var prevAnimEventBind : h3d.anim.Animation;
|
|
|
+
|
|
|
function set_bsX(v: Float) : Float {
|
|
|
if (v != bsX)
|
|
|
currentTriangle = -1;
|
|
@@ -50,6 +58,35 @@ class BlendSpace2D extends AnimNode {
|
|
|
var workQuats : Array<h3d.Quat> = [new h3d.Quat(), new h3d.Quat(), new h3d.Quat()];
|
|
|
var refQuat = new h3d.Quat();
|
|
|
|
|
|
+
|
|
|
+ static function halfLifeToDamping(halfLife: Float) {
|
|
|
+ return (4.0 * 0.69314718056) / (halfLife + 1e-5);
|
|
|
+ }
|
|
|
+
|
|
|
+ static function fastNegexp(x: Float) : Float
|
|
|
+ {
|
|
|
+ return 1.0 / (1.0 + x + 0.48*x*x + 0.235*x*x*x);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ inline static function criticalSpringDamper(x: Float, v: Float, xGloal: Float, vGoal: Float, halfLife: Float, dt: Float) : {x: Float, v: Float} {
|
|
|
+ final damping = halfLifeToDamping(halfLife);
|
|
|
+ final c = xGloal + (damping * vGoal) / (damping * damping ) / 4.0;
|
|
|
+ final half_damping = damping / 2.0;
|
|
|
+ final j0 = x - c;
|
|
|
+ final j1 = v + j0 * half_damping;
|
|
|
+ final eydt = fastNegexp(half_damping * dt);
|
|
|
+
|
|
|
+ return {x: eydt * (j0 + j1 * dt) + c, v: eydt *(v - j1*half_damping*dt)};
|
|
|
+ }
|
|
|
+
|
|
|
+ override function resetSmoothedValues() {
|
|
|
+ realX = bsX;
|
|
|
+ realY = bsY;
|
|
|
+ vX = 0.0;
|
|
|
+ vY = 0.0;
|
|
|
+ }
|
|
|
+
|
|
|
override function getBones(ctx: hrt.animgraph.nodes.AnimNode.GetBoneContext):Map<String, Int> {
|
|
|
var boneMap : Map<String, Int> = [];
|
|
|
animInfos = [];
|
|
@@ -57,6 +94,9 @@ class BlendSpace2D extends AnimNode {
|
|
|
triangles = [];
|
|
|
currentTriangle = -1;
|
|
|
|
|
|
+ realX = bsX;
|
|
|
+ realY = bsY;
|
|
|
+
|
|
|
var curOurBoneId = 0;
|
|
|
|
|
|
if (blendSpace == null) {
|
|
@@ -79,8 +119,8 @@ class BlendSpace2D extends AnimNode {
|
|
|
function makeAnim() : Int {
|
|
|
// Create a new animation
|
|
|
var index = animInfos.length;
|
|
|
- var animBase = hxd.res.Loader.currentInstance.load(path).toModel().toHmd().loadAnimation();
|
|
|
-
|
|
|
+ var animModel = hxd.res.Loader.currentInstance.load(path).toModel();
|
|
|
+ var animBase = ctx.modelCache.loadAnimation(animModel);
|
|
|
var proxy = new hrt.animgraph.nodes.Input.AnimProxy(null);
|
|
|
var animInstance = animBase.createInstance(proxy);
|
|
|
|
|
@@ -137,6 +177,26 @@ class BlendSpace2D extends AnimNode {
|
|
|
override function tick(dt:Float) {
|
|
|
super.tick(dt);
|
|
|
|
|
|
+ if (blendSpace.smoothX > 0) {
|
|
|
+ var r = criticalSpringDamper(realX, vX, bsX, 0, blendSpace.smoothX, dt);
|
|
|
+ realX = r.x;
|
|
|
+ vX = r.v;
|
|
|
+
|
|
|
+ currentTriangle = -1;
|
|
|
+ } else {
|
|
|
+ realX = bsX;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (blendSpace.smoothX > 0) {
|
|
|
+ var r = criticalSpringDamper(realY, vY, bsY, 0, blendSpace.smoothY, dt);
|
|
|
+ realY = r.x;
|
|
|
+ vY = r.v;
|
|
|
+
|
|
|
+ currentTriangle = -1;
|
|
|
+ } else {
|
|
|
+ realY = bsY;
|
|
|
+ }
|
|
|
+
|
|
|
for (animInfo in animInfos) {
|
|
|
// keep all the animations in sync
|
|
|
var scale = animInfo.selfSpeed;
|
|
@@ -159,7 +219,7 @@ class BlendSpace2D extends AnimNode {
|
|
|
return;
|
|
|
|
|
|
if (currentTriangle == -1) {
|
|
|
- var curPos = inline new h2d.col.Point(bsX, bsY);
|
|
|
+ var curPos = inline new h2d.col.Point(realX, realY);
|
|
|
|
|
|
// find the triangle our curPos resides in
|
|
|
var collided = false;
|
|
@@ -213,6 +273,22 @@ class BlendSpace2D extends AnimNode {
|
|
|
if (currentTriangle == -1)
|
|
|
throw "assert";
|
|
|
|
|
|
+ var max = 0;
|
|
|
+ for (i in 1...3) {
|
|
|
+ if (weights[i] > weights[max]) {
|
|
|
+ max = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var strongestAnim = triangles[currentTriangle][max].animInfo?.anim;
|
|
|
+ if (prevAnimEventBind != strongestAnim) {
|
|
|
+ if (prevAnimEventBind != null)
|
|
|
+ prevAnimEventBind.onEvent = null;
|
|
|
+ if (strongestAnim != null)
|
|
|
+ strongestAnim.onEvent = animEventHander;
|
|
|
+ prevAnimEventBind = strongestAnim;
|
|
|
+ }
|
|
|
+
|
|
|
currentAnimLenght = 0.0;
|
|
|
|
|
|
// Compensate for null animations that don't have length
|
|
@@ -290,6 +366,14 @@ class BlendSpace2D extends AnimNode {
|
|
|
outMatrix._23 = workQuat.w;
|
|
|
}
|
|
|
|
|
|
+ function animEventHander(name: String) {
|
|
|
+ onEvent(name);
|
|
|
+ }
|
|
|
+
|
|
|
+ function setupAnimEvents() {
|
|
|
+ // handled by the triangle setup
|
|
|
+ }
|
|
|
+
|
|
|
#if editor
|
|
|
override function getPropertiesHTML(width:Float):Array<hide.Element> {
|
|
|
var elts = super.getPropertiesHTML(width);
|