@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 6.48 kB
JavaScript
import{Vec2 as t}from"../../../core/math/vec2.js";import{Vec4 as i}from"../../../core/math/vec4.js";import{ORIENTATION_HORIZONTAL as n,ORIENTATION_VERTICAL as e}from"../../../scene/constants.js";import{FITTING_SHRINK as o,FITTING_BOTH as s,FITTING_STRETCH as r,FITTING_NONE as a}from"./constants.js";const c={};c[n]={axis:"x",size:"width",calculatedSize:"calculatedWidth",minSize:"minWidth",maxSize:"maxWidth",fitting:"widthFitting",fittingProportion:"fitWidthProportion"},c[e]={axis:"y",size:"height",calculatedSize:"calculatedHeight",minSize:"minHeight",maxSize:"maxHeight",fitting:"heightFitting",fittingProportion:"fitHeightProportion"};const h={};h[n]=e,h[e]=n;const l={minWidth:0,minHeight:0,maxWidth:Number.POSITIVE_INFINITY,maxHeight:Number.POSITIVE_INFINITY,width:null,height:null,fitWidthProportion:0,fitHeightProportion:0},u="NONE",g="APPLY_STRETCHING",f="APPLY_SHRINKING",x=new t;function m(t){let m;const z=c[t],d=c[h[t]];function p(t,i){return-i[z.size]*t.pivot[z.axis]}function S(t,i){return-i[d.size]*t.pivot[d.axis]}function I(t,i){return i[z.size]*(1-t.pivot[z.axis])}function N(t){const i=t.entity.layoutchild;return!i||!i.enabled||!i.excludeFromLayout}function P(t,i,n){switch(t){case a:return u;case r:return i<n?g:u;case o:return i>=n?f:u;case s:return i<n?g:f;default:throw new Error(`Unrecognized fitting mode: ${t}`)}}function y(t,i){return T(t,i.size)+(t.length-1)*m.spacing[i.axis]}function w(t,i,n){const e=Y(t,n.maxSize),o=b(t,n.fittingProportion),s=_(o,e);let r=x[n.axis]-i;for(let i=0;i<t.length;++i){const a=e[i],c=H(a,r,o,s),h=t[a][n.size]+c,l=t[a][n.maxSize],u=Math.min(h,l);t[a][n.size]=u;r-=c-Math.max(h-u,0)}}function E(t,i,n){const e=Y(t,n.minSize,!0),o=function(t){if(1===t.length)return[1];const i=[],n=t.length;for(let e=0;e<n;++e)i.push((1-t[e])/(n-1));return i}(b(t,n.fittingProportion)),s=_(o,e);let r=i-x[n.axis];for(let i=0;i<t.length;++i){const a=e[i],c=H(a,r,o,s),h=t[a][n.size]-c,l=t[a][n.minSize],u=Math.max(h,l);t[a][n.size]=u;r-=c-Math.max(u-h,0)}}function H(t,i,n,e){const o=n[t],s=e[t];return Math.abs(o)<1e-5&&Math.abs(s)<1e-5?i:i*o/s}function M(t){const i=[];for(let n=0;n<t.length;++n){const e=t[n],o=Math.max(v(e,"minWidth"),0),s=Math.max(v(e,"minHeight"),0),r=Math.max(v(e,"maxWidth"),o),a=Math.max(v(e,"maxHeight"),s),c=W(v(e,"width"),o,r),h=W(v(e,"height"),s,a),l=v(e,"fitWidthProportion"),u=v(e,"fitHeightProportion");i.push({minWidth:o,minHeight:s,maxWidth:r,maxHeight:a,width:c,height:h,fitWidthProportion:l,fitHeightProportion:u})}return i}function v(t,i){const n=t.entity.layoutchild;return n&&n.enabled&&void 0!==n[i]&&null!==n[i]?n[i]:void 0!==t[i]?t[i]:l[i]}function W(t,i,n){return Math.min(Math.max(t,i),n)}function T(t,i){return t.reduce(((t,n)=>t+n[i]),0)}function b(t,i){const n=T(t,i),e=[],o=t.length;if(0===n)for(let t=0;t<o;++t)e.push(1/o);else for(let s=0;s<o;++s)e.push(t[s][i]/n);return e}function Y(t,i,n){return t.forEach(F),t.slice().sort(((t,e)=>n?e[i]-t[i]:t[i]-e[i])).map(L)}function F(t,i){t.index=i}function L(t){return t.index}function _(t,i){const n=[];n[i[t.length-1]]=t[i[t.length-1]];for(let e=t.length-2;e>=0;--e)n[i[e]]=n[i[e+1]]+t[i[e]];return n}return function(t,s){t=t.filter(N),m=s,x.x=m.containerSize.x-m.padding.x-m.padding.z,x.y=m.containerSize.y-m.padding.y-m.padding.w,function(t){for(let n=0;n<t.length;++n){const e=t[n],o=e.anchor;0===o.x&&0===o.y&&0===o.z&&0===o.w||(e.anchor=i.ZERO)}}(t);const r=function(t){const i=m.orientation===n&&m.reverseX||m.orientation===e&&m.reverseY,o=m.orientation===n&&m.reverseY||m.orientation===e&&m.reverseX;if(i)for(let n=0;n<t.length;++n)i&&t[n].reverse();o&&t.reverse();return t}(function(t){if(!m.wrap)return[t];const i=[[]],n=M(t);let e=0;const s=m[z.fitting]===o;for(let o=0;o<t.length;++o){i[i.length-1].length>0&&(e+=m.spacing[z.axis]);const r=n[o][z.size];e+=r,!s&&e>x[z.axis]&&0!==i[i.length-1].length&&(e=r,i.push([])),i[i.length-1].push(t[o]),s&&e>x[z.axis]&&o!==t.length-1&&(e=0,i.push([]))}return i}(t)),a=function(t,i){const n=[],e=[];for(let o=0;o<t.length;++o){const s=t[o];s.largestElement=null,s.largestSize={width:Number.NEGATIVE_INFINITY,height:Number.NEGATIVE_INFINITY};for(let t=0;t<s.length;++t){const n=i[o][t];n[d.size]>s.largestSize[d.size]&&(s.largestElement=s[t],s.largestSize=n)}n.push(s.largestElement),e.push(s.largestSize)}const o=y(e,d),s=P(m[d.fitting],o,x[d.axis]);s===g?w(e,o,d):s===f&&E(e,o,d);for(let n=0;n<t.length;++n){const e=t[n];for(let o=0;o<e.length;++o){const s=i[n][o],r=s[d.size],a=1===t.length?x[d.axis]:e.largestSize[d.size],c=P(m[d.fitting],r,a);c===g?s[d.size]=Math.min(a,s[d.maxSize]):c===f&&(s[d.size]=Math.max(a,s[d.minSize]))}}return i}(r,function(t){const i=[];for(let n=0;n<t.length;++n){const e=M(t[n]),o=y(e,z),s=P(m[z.fitting],o,x[z.axis]);s===g?w(e,o,z):s===f&&E(e,o,z),i.push(e)}return i}(r)),c=function(t,i){const n={};n[z.axis]=0,n[d.axis]=0,t[z.size]=Number.NEGATIVE_INFINITY;const e=[];for(let o=0;o<t.length;++o){const s=t[o];if(0===s.length){e.push([]);continue}const r=[],a=i[o];for(let t=0;t<s.length;++t){const i=s[t],e=a[t];n[d.axis]-=S(i,e),n[z.axis]-=p(i,e),r[t]={},r[t][z.axis]=n[z.axis],r[t][d.axis]=n[d.axis],n[d.axis]+=S(i,e),n[z.axis]+=I(i,e)+m.spacing[z.axis]}s[z.size]=n[z.axis]-m.spacing[z.axis],s[d.size]=s.largestSize[d.size],t[z.size]=Math.max(t[z.size],s[z.size]),n[z.axis]=0,n[d.axis]+=s[d.size]+m.spacing[d.axis],e.push(r)}return t[d.size]=n[d.axis]-m.spacing[d.axis],e}(r,a);return function(t,i,n){const e=m.alignment[z.axis],o=m.alignment[d.axis],s=m.padding[z.axis],r=m.padding[d.axis];for(let a=0;a<t.length;++a){const c=t[a],h=i[a],l=n[a],u=(x[z.axis]-c[z.size])*e+s,g=(x[d.axis]-t[d.size])*o+r;for(let t=0;t<c.length;++t){const i=(c[d.size]-h[t][d.size])*m.alignment[d.axis];l[t][z.axis]+=u,l[t][d.axis]+=g+i}}}(r,a,c),function(t,i,e){for(let o=0;o<t.length;++o){const s=t[o],r=i[o],a=e[o];for(let t=0;t<s.length;++t){const i=s[t];i[z.calculatedSize]=r[t][z.size],i[d.calculatedSize]=r[t][d.size],m.orientation===n?i.entity.setLocalPosition(a[t][z.axis],a[t][d.axis],i.entity.getLocalPosition().z):i.entity.setLocalPosition(a[t][d.axis],a[t][z.axis],i.entity.getLocalPosition().z)}}}(r,a,c),function(t){const n=t.width,e=t.height,o=(x.x-n)*m.alignment.x+m.padding.x,s=(x.y-e)*m.alignment.y+m.padding.y;return{bounds:new i(o,s,n,e)}}(r)}}const z={};z[n]=m(n),z[e]=m(e);class d{calculateLayout(t,i){const n=z[i.orientation];if(n)return n(t,i);throw new Error(`Unrecognized orientation value: ${i.orientation}`)}}export{d as LayoutCalculator};