UNPKG

animouse

Version:

lightweight animation state machine for three js

3 lines (2 loc) 21.6 kB
import{MathUtils as t,LoopOnce as i,Vector2 as s}from"three";var n;(t=>{t.ENTER="enter",t.EXIT="exit",t.PLAY="play",t.STOP="stop",t.ITERATE="iterate",t.FINISH="finish"})(n||(n={}));const r=1e-6,o=2*Math.PI;let e=0;function h(){return e++}function a(t,i){if(!Number.isFinite(t))throw Error(i+": value must be a finite number");if(Math.abs(t)>Number.MAX_SAFE_INTEGER)throw Error(i+": value exceeds maximum safe integer range")}function c(t,i){if(a(t,i),0>t||t>o)throw Error(i+": azimuth must be between 0 and 2π radians")}function u(t,i){if(a(t,i),0>t||t>1)throw Error(i+": value must be between 0 and 1")}function f(t,i){if(a(t,i),r>t)throw Error(i+": value must be greater than or equal to 0.000001")}function l(t,i){if(a(t,i),0>t)throw Error(i+": value must be greater than or equal to 0")}class d{constructor(t,i){this.A=[],this.T=new Map,this.$=new Map,this.I=new Map,this._=t,this._.onEnterInternal(),this._.setInfluenceInternal(1),this.C=i,this.T=new Map}get currentState(){return this._}addEventTransition(t,i){if(l(i.duration,"Event transition duration"),i.from===i.to)throw Error("Event animation transition can't create a recursive loop to itself");const s=this.T.get(t)??[];if(!i.condition)for(const t of s)if(!t.condition&&t.from===i.from)throw Error("Event animation transition already exists");s.push(i),this.T.set(t,s)}addAutomaticTransition(t,i){if(l(i.duration,"Automatic transition duration"),t===i.to)throw Error("Automatic animation transition can't create a recursive loop to itself");if(this.$.has(t))throw Error("Automatic transition already exists");this.$.set(t,i),t.on(n.ITERATE,this.D,this),t.on(n.FINISH,this.D,this)}addDataTransition(t,i){if(l(i.duration,"Data transition duration"),t===i.to)throw Error("Automatic animation transition can't create a recursive loop to itself");const s=this.I.get(t)??[];s.push(i),this.I.set(t,s)}handleEvent(t,...i){const s=this.T.get(t);if(void 0===s)return!1;for(const{from:n,to:r,duration:o,condition:e}of s){const s=!n||n===this._,h=!e||e(n,r,t,...i);if(s&&h)return this.B(r,o)}return!1}update(i){l(i,"Delta time"),this._.influence>0&&this._.onTickInternal(i);for(const t of this.A)t.influence>0&&t.onTickInternal(i);const s=this.I.get(this._)?.find(t=>t.condition(this._,t.to,...t.data??[]));if(s&&this.B(s.to,s.duration),void 0!==this.q){const s=0===this.q?1:Math.min(1,i/this.q);for(const i of this.A)i.setInfluenceInternal(t.lerp(i.influence,0,s));if(this._.setInfluenceInternal(t.lerp(this._.influence,1,s)),this.q=Math.max(0,this.q-i),0===this.q){for(const t of this.A)t.setInfluenceInternal(0);this.A=[],this._.setInfluenceInternal(1),this.q=void 0}}this.C.update(i)}B(t,i){return this._!==t&&(this.A=this.A.filter(i=>i!==t),this.A.push(this._),this._.onExitInternal(),this._=t,this._.onEnterInternal(),this.q=i,!0)}D(t,i){if(i===this._){const t=this.$.get(this._);t&&this.B(t.to,t.duration)}}}class v{constructor(t,i,s=0){this.t=new WeakMap,this.i=new Map,void 0!==t&&(void 0===i?this.i.set(t,s):this.t.set(i,new Map([[t,s]])))}insert(t,i,s=0){if(void 0===i){if(this.i.has(t))return;return void this.i.set(t,s)}const n=this.t.get(i);void 0===n?this.t.set(i,new Map([[t,s]])):n.has(t)||n.set(t,s)}remove(t,i){if(void 0===i)return void this.i.delete(t);const s=this.t.get(i);void 0!==s&&(s.delete(t),0===s.size&&this.t.delete(i))}has(t,i){if(void 0===i)return this.i.has(t);const s=this.t.get(i);return void 0!==s&&s.has(t)}getPriority(t,i){if(void 0===i)return this.i.get(t);const s=this.t.get(i);return void 0!==s?s.get(t):void 0}}class p{constructor(){this.o=new Map}on(t,i,s,n=0){return this.h(t,!1,n,i,s),this}once(t,i,s,n=0){return this.h(t,!0,n,i,s),this}off(t,i,s){const n=this.o.get(t);if(void 0===n)return this;n.u&&(n.u=!1,n.v=n.v.slice());const r=n.v;if(0===r.length)return this.o.delete(t),this;if(void 0===i){this.o.delete(t);for(let t=0;r.length>t;t++){const i=r[t];n.l.remove(i.S,i.p)}return this}{const o=r.length;if(r[0].S===i&&r[0].p===s)return 1===o?this.o.delete(t):r.shift(),this;const e=o-1;if(r[e].S===i&&r[e].p===s)return r.pop(),this;if(10>o||r[0].M===r[e].M)for(let t=1;e>t;t++){const n=r[t];if(n.S===i&&n.p===s)return r.splice(t,1),this}else{const t=n.l.getPriority(i,s);if(void 0===t)return this;let o=0,e=r.length-1;for(;e>=o;){const i=o+e>>>1;t>r[i].M?o=i+1:e=i-1}const h=o;for(e=r.length-1;e>=o;){const i=o+e>>>1;r[i].M>t?e=i-1:o=i+1}const a=e;for(let t=h;a>=t;t++)if(r[t].S===i&&r[t].p===s)return r.splice(t,1),this}}return this}emit(t,...i){const s=this.o.get(t);if(void 0===s)return!1;if(0===s.v.length)return!1;s.u?s.v=s.v.slice():s.u=!0;const n=s.v;let r=!1;for(let t=0;n.length>t;t++){const s=n[t];s.S.apply(s.p,i),s.k&&(r=!0,s.m=!0)}const o=this.o.get(t);if(void 0===o)return!0;o.v===n&&(o.u=!1);const e=o.v;if(r){let i=0;for(let t=0;e.length>t;t++){const s=e[t];s.m?o.l.remove(s.S,s.p):e[i++]=s}0===i?this.o.delete(t):e.length=i}return!0}h(t,i,s,n,r){let o=this.o.get(t);if(void 0===o)return void this.o.set(t,{v:[{S:n,p:r,M:s,k:i,m:!1}],u:!1,l:new v(n,r,s)});if(o.l.has(n,r))throw Error("Event listener already exists");o.l.insert(n,r,s);const e={S:n,p:r,M:s,k:i,m:!1};o.u&&(o.u=!1,o.v=o.v.slice());{const t=o.v,i=e.M;if(0===t.length||i>=t[t.length-1].M)return void t.push(e);if(t[0].M>=i)return void t.unshift(e);{let s=0,n=t.length;for(;n>s;){const r=s+n>>>1;i>t[r].M?s=r+1:n=r}t.splice(s,0,e)}}}}class m extends p{constructor(){super(...arguments),this.name="",this.influenceInternal=0,this.timeEvents=new Map}get influence(){return this.influenceInternal}onEnterInternal(){this.emit(n.ENTER,this)}onExitInternal(){this.emit(n.EXIT,this)}onTimeEventInternal(t,i,s,n){u(i,"Unit time");const r=Math.round(100*i)/100,o=this.timeEvents.get(t)??new Map;this.timeEvents.set(t,o);const e=o.get(r)??`${r}_${t.index}`;o.set(r,e),n?this.once(e,s):this.on(e,s)}offTimeEventInternal(t,i,s){u(i,"Unit time");const n=Math.round(100*i)/100,r=this.timeEvents.get(t);if(!r)return;const o=r.get(n);o&&(this.off(o,s),r.delete(n),0===r.size&&this.timeEvents.delete(t))}updateAnchorTime(t,i){const s=t.action;if(0===t.action.weight)throw Error("Cannot update anchor time for a non-running action: "+this.name);const n=s.time,r=t.duration;r>n&&n+i>=r&&this.emit(t.iterationEventType,s,this)}resetFinishedAction(t){const s=t.action;s.loop===i&&s.time===t.duration&&(s.time=0,s.paused=!1,s.enabled=!0)}processTimeEvents(t,i){const s=this.timeEvents.get(t);if(s){const n=t.action,r=i*t.invDuration;for(const[i,o]of s){const s=n.time*t.invDuration;i>s&&s+r>=i&&this.emit(o,n,this)}}}}class w extends m{constructor(t){super();const s=t.getClip().duration;f(s,"Clip duration"),t.stop(),t.time=0,t.weight=0,t.paused=!1,t.enabled=!1,this.W={index:h(),action:t,get weight(){throw Error("ClipState weight is not accessible")},duration:s,invDuration:1/s,iterationEventType:t.loop===i?n.FINISH:n.ITERATE}}onTimeEvent(t,i){this.onTimeEventInternal(this.W,t,i,!1)}onceTimeEvent(t,i){this.onTimeEventInternal(this.W,t,i,!0)}offTimeEvent(t,i){this.offTimeEventInternal(this.W,t,i)}setInfluenceInternal(t){if(u(t,"Influence"),this.influenceInternal===t)return;this.influenceInternal=t;const i=this.W.action;t>0&&0===i.weight?(i.enabled=!0,i.paused=!1,i.time=0,i.play(),this.emit(n.PLAY,i,this)):0===t&&i.weight>0&&(i.stop(),i.time=0,i.paused=!1,i.enabled=!1,this.emit(n.STOP,i,this)),i.weight=t}onTickInternal(t){if(0===this.influence)throw Error(this.name+": cannot update anchor time because the animation influence is zero");this.processTimeEvents(this.W,t),this.updateAnchorTime(this.W,t)}onEnterInternal(){super.onEnterInternal(),this.influence>0&&this.resetFinishedAction(this.W)}}function x(t,i,s){a(t.x,"a.x"),a(t.y,"a.y"),a(i.x,"b.x"),a(i.y,"b.y"),a(s.x,"c.x"),a(s.y,"c.y");const n={x:i.x-t.x,y:i.y-t.y},o={x:s.x-t.x,y:s.y-t.y},e=n.x*n.x+n.y*n.y,h=n.x*o.x+n.y*o.y,c=o.x*o.x+o.y*o.y,u=e*c-h*h;if(r>Math.abs(u))throw Error(`Degenerate triangle detected: determinant is too close to zero (${u}). Triangle points are a(${t.x}, ${t.y}), b(${i.x}, ${i.y}), c(${s.x}, ${s.y}).`);const f=2*(n.x*o.y-n.y*o.x),l={x:t.x+(o.y*e-n.y*c)/f,y:t.y+(n.x*c-o.x*e)/f};return{origin:t,circumcenter:l,circumradiusSquared:(t.x-l.x)**2+(t.y-l.y)**2,u:n,v:o,d00:e,d01:h,d11:c,invDenom:1/u,min:{x:Math.min(t.x,i.x,s.x),y:Math.min(t.y,i.y,s.y)},max:{x:Math.max(t.x,i.x,s.x),y:Math.max(t.y,i.y,s.y)}}}function E(t,i){if(a(t.x,"point.x"),a(t.y,"point.y"),a(i.origin.x,"cache.origin.x"),a(i.origin.y,"cache.origin.y"),a(i.min.x,"cache.min.x"),a(i.min.y,"cache.min.y"),a(i.max.x,"cache.max.x"),a(i.max.y,"cache.max.y"),a(i.u.x,"cache.u.x"),a(i.u.y,"cache.u.y"),a(i.v.x,"cache.v.x"),a(i.v.y,"cache.v.y"),a(i.d00,"cache.d00"),a(i.d01,"cache.d01"),a(i.d11,"cache.d11"),a(i.invDenom,"cache.invDenom"),i.min.x>t.x||t.x>i.max.x||i.min.y>t.y||t.y>i.max.y)return;const s=t.x-i.origin.x,n=t.y-i.origin.y,r=s*i.u.x+n*i.u.y,o=s*i.v.x+n*i.v.y,e=(i.d11*r-i.d01*o)*i.invDenom;if(0>e)return;const h=(i.d00*o-i.d01*r)*i.invDenom;if(0>h)return;const c=1-e-h;return 0>c?void 0:{aW:c,bW:e,cW:h}}function g(t,i,s){return a(t.x,"origin.x"),a(t.y,"origin.y"),f(i,"radiusSquared"),a(s.x,"point.x"),a(s.y,"point.y"),i-r>(s.x-t.x)**2+(s.y-t.y)**2}function y(t){a(t,"Azimuth for normalization");const i=t%o;return 0>i?i+o:i}function M(t,i){c(t,"Azimuth 'from'"),c(i,"Azimuth 'to'");const s=i-t;return 0>s?s+o:s}function b(t,i,s){return c(t,"Azimuth value"),c(i,"Azimuth 'from'"),c(s,"Azimuth 'to'"),i>s?t>=i||s>=t:t>=i&&s>=t}function A(t,i,s,n){return a(t,"Coordinate 'x1'"),a(i,"Coordinate 'y1'"),a(s,"Coordinate 'x2'"),a(n,"Coordinate 'y2'"),(s-t)**2+(n-i)**2}function T([t,i],s,n){a(t.x,"Coordinate 'p1.x'"),a(t.y,"Coordinate 'p1.y'"),a(i.x,"Coordinate 'p2.x'"),a(i.y,"Coordinate 'p2.y'"),a(s,"Coordinate 'x'"),a(n,"Coordinate 'y'");const r=i.x-t.x,o=i.y-t.y,e=((s-t.x)*r+(n-t.y)*o)/(r*r+o*o),h=e>0?1>e?e:1:0;return(s-(t.x+h*r))**2+(n-(t.y+h*o))**2}class ${static triangulate(t){if(3>t.length)throw Error("At least 3 points are required for triangulation, but got "+t.length);for(const i of t)a(i.x,"x-coordinate"),a(i.y,"y-coordinate");for(let i=0;t.length-1>i;i++){const s=t[i].x,n=t[i].y;for(let o=i+1;t.length>o;o++)if(r>Math.abs(s-t[o].x)&&r>Math.abs(n-t[o].y))throw Error(`Duplicate points found at indices ${i} and ${o}: (${s}, ${n})`)}{const[i,n,...o]=t,e=(new s).subVectors(n,i).normalize(),h=new s;if(o.every(t=>Math.abs(e.cross(h.subVectors(t,i)))<r))throw Error("All points are collinear - cannot run triangulation")}const i=$.buildSuperTriangle(t);let n=[i];for(const i of t){const t=$.filterBadTriangles(n,i);for(const s of $.buildPolygon(t))n.push({a:s[0],b:s[1],c:i,...x(s[0],s[1],i)})}const o=$.filterSuperTriangleVertices(n,i);for(const[t,i]of o)if(2!==i.length)throw Error(`Invariant violation: outer edge point (${t.x}, ${t.y}) has ${i.length} connections (expected 2)`);return{triangles:n,boundaryEdgeMap:o}}static filterBadTriangles(t,i){const s=[];let n=0;for(const r of t)g(r.circumcenter,r.circumradiusSquared,i)?s.push(r):t[n++]=r;return t.length=n,s}static buildPolygon(t){const i=[];for(const s of t){const n=[[s.a,s.b],[s.b,s.c],[s.c,s.a]];for(const r of n){const n=t.every(t=>s===t||[[t.a,t.b],[t.b,t.c],[t.c,t.a]].every(t=>!(r[0]===t[0]&&r[1]===t[1]||r[1]===t[0]&&r[0]===t[1])));n&&i.push(r)}}return i}static filterSuperTriangleVertices(t,i){const s=new Map;let n=0;for(const r of t){const o=[];if($.isVertexFromTriangle(r.a,i)||o.push(r.a),$.isVertexFromTriangle(r.b,i)||o.push(r.b),$.isVertexFromTriangle(r.c,i)||o.push(r.c),2===o.length){const[t,i]=o,n=s.get(t)??[],r=s.get(i)??[];n.push(i),r.push(t),s.set(t,n),s.set(i,r)}3===o.length&&(t[n++]=r)}return t.length=n,s}static buildSuperTriangle(t){let i=1/0,s=1/0,n=-1/0,r=-1/0;for(const o of t)i=Math.min(i,o.x),s=Math.min(s,o.y),n=Math.max(n,o.x),r=Math.max(r,o.y);const o=16*Math.max(n-i,r-s),e={x:i-o,y:s-o},h={x:i+2*o,y:s-o},a={x:i+o,y:s+2*o};return{a:e,b:h,c:a,...x(e,h,a)}}static isVertexFromTriangle(t,i){return t===i.a||t===i.b||t===i.c}}class I extends m{constructor(){super(...arguments),this.actionToAnchor=new Map}onTimeEvent(t,i,s){const n=this.actionToAnchor.get(t);if(!n)throw Error("Action is not registered");this.onTimeEventInternal(n,i,s,!1)}onceTimeEvent(t,i,s){const n=this.actionToAnchor.get(t);if(!n)throw Error("Action is not registered");this.onTimeEventInternal(n,i,s,!0)}offTimeEvent(t,i,s){const n=this.actionToAnchor.get(t);if(!n)throw Error("Action is not registered");this.offTimeEventInternal(n,i,s)}setInfluenceInternal(t){u(t,"Animation tree influence"),t!==this.influenceInternal&&(this.influenceInternal=t,this.updateAnchorsInfluence())}updateAnchorWeight(t,i=t.weight){u(i,"Anchor weight"),t.weight=i;const s=i*this.influenceInternal,r=t.action;s!==r.weight&&(s>0&&0===r.weight?(r.enabled=!0,r.paused=!1,r.time=0,r.play(),this.emit(n.PLAY,r,this)):0===s&&r.weight>0&&(r.stop(),r.time=0,r.paused=!1,r.enabled=!1,this.emit(n.STOP,r,this)),r.weight=s)}}class z extends I{constructor(t){if(super(),this.P=new Map,this.F=[],this.N=[],this.V=new Map,this.U=0,this.L=0,3>t.length)throw Error("FreeformBlendTree requires at least 3 actions for triangulation");for(let i=0;t.length>i;i++)a(t[i].x,`Freeform action at index ${i} x value`),a(t[i].y,`Freeform action at index ${i} y value`);for(let i=0;t.length-1>i;i++){const s=t[i].x,n=t[i].y;for(let o=i+1;t.length>o;o++)if(r>Math.abs(s-t[o].x)&&r>Math.abs(n-t[o].y))throw Error(`Duplicate coordinates found, x: ${s}, y: ${n}. All action values must be unique.`)}const s=[];for(const r of t){const t=r.action;t.stop(),t.time=0,t.weight=0,t.paused=!1,t.enabled=!1;const o=t.getClip().duration;if(0>=o)throw Error("Action duration must be greater than zero");const e={index:h(),action:t,weight:0,duration:o,invDuration:1/o,iterationEventType:t.loop===i?n.FINISH:n.ITERATE,x:r.x,y:r.y};s.push(e),this.actionToAnchor.set(t,e)}const o=$.triangulate(s);this.N=o.triangles.map(t=>{const{circumcenter:i,circumradiusSquared:s,...n}=t;return{...n,centroid:(r=t.a,o=t.b,e=t.c,a(r.x,"a.x"),a(r.y,"a.y"),a(o.x,"b.x"),a(o.y,"b.y"),a(e.x,"c.x"),a(e.y,"c.y"),{x:(r.x+o.x+e.x)/3,y:(r.y+o.y+e.y)/3})};var r,o,e}),this.V=o.boundaryEdgeMap,this.R(),this.j()}get blendValue(){return{x:this.U,y:this.L}}setBlend(t,i){a(t,"Blend x"),a(i,"Blend y"),this.U===t&&this.L===i||(this.U=t,this.L=i,this.R(),this.j())}onTickInternal(t){if(0===this.influence)throw Error(this.name+": cannot update anchor time because the animation influence is zero");for(const i of this.F)this.processTimeEvents(i,t),this.updateAnchorTime(i,t)}onEnterInternal(){if(super.onEnterInternal(),this.influence>0)for(const t of this.F)this.resetFinishedAction(t)}updateAnchorsInfluence(){for(const t of this.F)this.updateAnchorWeight(t)}j(){this.P.clear();for(const t of this.F)this.P.set(t,0);this.G(this.P)||this.H(this.P),this.F.length=0;for(const[t,i]of this.P)this.updateAnchorWeight(t,i),i>0&&this.F.push(t)}G(t){const i={x:this.U,y:this.L};for(const s of this.N){const n=E(i,s);if(n)return t.set(s.a,n.aW),t.set(s.b,n.bW),t.set(s.c,n.cW),!0}return!1}H(t){const i=this.N[0],s=[i.a,i.b,i.c].reduce((t,i)=>A(t.x,t.y,this.U,this.L)<A(i.x,i.y,this.U,this.L)?t:i),n=this.V.get(s);if(void 0===n)throw Error(`Invariant violation: no edge data found for outer vertex (${s.x}, ${s.y})`);const r=[s,n[0]],o=[s,n[1]],e=T(r,this.U,this.L)<T(o,this.U,this.L)?r:o,[h,a]=e,c=a.x-h.x,u=a.y-h.y,f=Math.max(0,Math.min(1,((this.U-h.x)*c+(this.L-h.y)*u)/(c*c+u*u)));t.set(h,1-f),t.set(a,f)}R(){this.N.sort((t,i)=>A(t.centroid.x,t.centroid.y,this.U,this.L)-A(i.centroid.x,i.centroid.y,this.U,this.L))}}class _ extends I{constructor(t){if(super(),this.J=[],this.K=0,2>t.length)throw Error("Need at least 2 actions");for(let i=0;t.length>i;i++)a(t[i].value,`Linear action at index ${i} value`);for(let i=0;t.length-1>i;i++){const s=t[i].value;for(let n=i+1;t.length>n;n++)if(r>Math.abs(s-t[n].value))throw Error(`Duplicate value found, value: ${s}. All action values must be unique.`)}for(const s of t){const t=s.action;t.stop(),t.time=0,t.weight=0,t.paused=!1,t.enabled=!1;const r=t.getClip().duration;f(r,"Clip duration");const o={index:h(),action:t,weight:0,duration:r,invDuration:1/r,iterationEventType:t.loop===i?n.FINISH:n.ITERATE,value:s.value};this.J.push(o),this.actionToAnchor.set(t,o)}this.J.sort((t,i)=>t.value-i.value),this.j()}get blendValue(){return this.K}setBlend(t){a(t,"Blend value"),t!==this.K&&(this.K=t,this.j())}onTickInternal(t){if(0===this.influence)throw Error(this.name+": cannot update anchor time because the animation influence is zero");this.O?.weight&&(this.processTimeEvents(this.O,t),this.updateAnchorTime(this.O,t)),this.X?.weight&&(this.processTimeEvents(this.X,t),this.updateAnchorTime(this.X,t))}onEnterInternal(){super.onEnterInternal(),this.influence>0&&(this.O&&this.resetFinishedAction(this.O),this.X&&this.resetFinishedAction(this.X))}updateAnchorsInfluence(){this.O&&this.updateAnchorWeight(this.O),this.X&&this.updateAnchorWeight(this.X)}j(){const t=this.J[0];if(t.value>=this.K)return this.O&&this.O!==t&&this.updateAnchorWeight(this.O,0),this.X&&this.updateAnchorWeight(this.X,0),this.updateAnchorWeight(t,1),this.O=t,void(this.X=void 0);const i=this.J[this.J.length-1];if(this.K>=i.value)return this.X&&this.X!==i&&this.updateAnchorWeight(this.X,0),this.O&&this.updateAnchorWeight(this.O,0),this.updateAnchorWeight(i,1),this.X=i,void(this.O=void 0);{let t=1,i=this.J.length-1;for(;i>t;){const s=t+i>>>1;this.K>this.J[s].value?t=s+1:i=s}const s=this.J[t-1],n=this.J[t];this.O&&this.O!==s&&this.O!==n&&this.updateAnchorWeight(this.O,0),this.X&&this.X!==s&&this.X!==n&&this.updateAnchorWeight(this.X,0);const r=(this.K-s.value)/(n.value-s.value);this.updateAnchorWeight(s,1-r),this.updateAnchorWeight(n,r),this.O=s,this.X=n}}}class C extends I{constructor(t,s){if(super(),this.P=new Map,this.F=[],this.Y=[],this.Z=[],this.tt=0,this.it=0,2>t.length)throw Error("At least 2 actions are required for polar blend tree");for(let i=0;t.length>i;i++){const{radius:s,azimuth:n}=t[i];a(s,`Polar action at index ${i} radius`),a(n,`Polar action at index ${i} azimuth`),f(s,`Polar action at index ${i} radius`)}for(const i of t)i.azimuth=y(i.azimuth);for(let i=0;t.length-1>i;i++){const s=t[i].azimuth,n=t[i].radius;for(let o=i+1;t.length>o;o++)if(r>Math.abs(s-t[o].azimuth)&&r>Math.abs(n-t[o].radius))throw Error(`Duplicate coordinates found, azimuth: ${s}, radius: ${n}. All action values must be unique.`)}for(const s of t){const t=s.action,o=t.getClip().duration;f(o,"Clip duration"),t.stop(),t.time=0,t.weight=0,t.paused=!1,t.enabled=!1;const e={index:h(),action:t,weight:0,duration:o,invDuration:1/o,iterationEventType:t.loop===i?n.FINISH:n.ITERATE,radius:s.radius,azimuth:s.azimuth},a=this.Y.find(t=>r>Math.abs(t.azimuth-s.azimuth)),c=this.Z.find(t=>r>Math.abs(t.radius-s.radius));a?a.anchors.push(e):this.Y.push({azimuth:e.azimuth,anchors:[e]}),c?c.anchors.push(e):this.Z.push({radius:e.radius,anchors:[e]}),this.actionToAnchor.set(t,e)}if(2>this.Y.length)throw Error("At least two rays are required.");const o=this.Z.length;if(this.Y.some(t=>t.anchors.length!==o))throw Error("The anchors must form a valid grid.");this.Y.sort((t,i)=>t.azimuth-i.azimuth);for(const t of this.Y)t.anchors.sort((t,i)=>t.radius-i.radius);this.Z.sort((t,i)=>t.radius-i.radius);for(const t of this.Z)t.anchors.sort((t,i)=>t.azimuth-i.azimuth);if(s){const t=s.getClip().duration;f(t,"Center clip duration"),s.stop(),s.time=0,s.weight=0,s.paused=!1,s.enabled=!1,this.st={index:h(),action:s,weight:1,duration:t,invDuration:1/t,iterationEventType:s.loop===i?n.FINISH:n.ITERATE,get radius(){throw Error("PolarBlendTree central anchor radius is not accessible")},get azimuth(){throw Error("PolarBlendTree central anchor azimuth is not accessible")}},this.F.push(this.st),this.actionToAnchor.set(s,this.st)}else this.j()}get blendValue(){return{azimuth:this.it,radius:this.tt}}setBlend(t,i){a(t,"Blend azimuth"),l(i,"Blend radius");const s=y(t);this.tt===i&&this.it===s||(this.tt=i,this.it=s,this.j())}onTickInternal(t){if(0===this.influence)throw Error(this.name+": cannot update anchor time because the animation influence is zero");for(const i of this.F)this.processTimeEvents(i,t),this.updateAnchorTime(i,t)}onEnterInternal(){if(super.onEnterInternal(),this.influence>0)for(const t of this.F)this.resetFinishedAction(t)}updateAnchorsInfluence(){for(const t of this.F)this.updateAnchorWeight(t)}j(){this.P.clear();for(const t of this.F)this.P.set(t,0);for(let t=0;this.Y.length>t;t++){const i=(t+1)%this.Y.length,s=this.Y[t],n=this.Y[i],r=s.azimuth,o=n.azimuth;if(b(this.it,r,o)){const e=M(r,o),h=M(r,this.it)/e,a=1-h;if(this.tt>this.Z[0].radius)if(this.Z[this.Z.length-1].radius>this.tt)this.nt(this.P,a,h,t,i);else{let t=h;this.P.set(s.anchors[s.anchors.length-1],a),this.P.set(n.anchors[n.anchors.length-1],t)}else{let t=a,i=h;if(this.st){const s=this.tt/this.Z[0].radius;this.P.set(this.st,1-s),t*=s,i*=s}this.P.set(s.anchors[0],t),this.P.set(n.anchors[0],i)}break}}this.F.length=0;for(const[t,i]of this.P)this.updateAnchorWeight(t,i),i>0&&this.F.push(t)}nt(t,i,s,n,r){for(let o=0;this.Z.length-1>o;o++){const e=this.Z[o],h=this.Z[o+1],a=e.radius,c=h.radius;if(this.tt>=a&&c>=this.tt){const o=(this.tt-a)/(c-a),u=1-o;return t.set(h.anchors[n],o*i),t.set(h.anchors[r],o*s),t.set(e.anchors[n],u*i),void t.set(e.anchors[r],u*s)}}throw Error(`Invariant violation: currentRadius ${this.tt} not found within any ring interval`)}}export{d as AnimationMachine,m as AnimationState,n as AnimationStateEvent,w as ClipState,r as EPSILON,z as FreeformBlendTree,_ as LinearBlendTree,o as PI2,C as PolarBlendTree,c as assertValidAzimuth,l as assertValidNonNegativeNumber,a as assertValidNumber,f as assertValidPositiveNumber,u as assertValidUnitRange,h as getNextAnchorIndex}; //# sourceMappingURL=index.min.js.map