UNPKG

@animech-public/playcanvas

Version:
2 lines (1 loc) 18.5 kB
import{math as t}from"../../../core/math/math.js";import{Vec2 as e}from"../../../core/math/vec2.js";import{Vec3 as i}from"../../../core/math/vec3.js";import{ORIENTATION_HORIZONTAL as n,ORIENTATION_VERTICAL as l}from"../../../scene/constants.js";import{GraphNode as o}from"../../../scene/graph-node.js";import{ElementDragHelper as s}from"../element/element-drag-helper.js";import{SCROLL_MODE_INFINITE as r,SCROLL_MODE_BOUNCE as a,SCROLL_MODE_CLAMP as h,SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED as c,SCROLLBAR_VISIBILITY_SHOW_ALWAYS as _}from"./constants.js";import{Component as b}from"../component.js";import{EVENT_MOUSEWHEEL as u}from"../../../platform/input/constants.js";const y=new e;class E extends b{constructor(t,o){super(t,o),this._viewportEntity=null,this._contentEntity=null,this._horizontalScrollbarEntity=null,this._verticalScrollbarEntity=null,this._evtElementRemove=null,this._evtViewportElementRemove=null,this._evtViewportResize=null,this._evtContentEntityElementAdd=null,this._evtContentElementRemove=null,this._evtContentResize=null,this._evtHorizontalScrollbarAdd=null,this._evtHorizontalScrollbarRemove=null,this._evtHorizontalScrollbarValue=null,this._evtVerticalScrollbarAdd=null,this._evtVerticalScrollbarRemove=null,this._evtVerticalScrollbarValue=null,this._scrollbarUpdateFlags={},this._scrollbarEntities={},this._prevContentSizes={},this._prevContentSizes[n]=null,this._prevContentSizes[l]=null,this._scroll=new e,this._velocity=new i,this._dragStartPosition=new i,this._disabledContentInput=!1,this._disabledContentInputEntities=[],this._toggleLifecycleListeners("on"),this._toggleElementListeners("on")}get data(){const t=this.system.store[this.entity.getGuid()];return t?t.data:null}set enabled(t){this._setValue("enabled",t)}get enabled(){return this.data.enabled}set horizontal(t){this._setValue("horizontal",t)}get horizontal(){return this.data.horizontal}set vertical(t){this._setValue("vertical",t)}get vertical(){return this.data.vertical}set scrollMode(t){this._setValue("scrollMode",t)}get scrollMode(){return this.data.scrollMode}set bounceAmount(t){this._setValue("bounceAmount",t)}get bounceAmount(){return this.data.bounceAmount}set friction(t){this._setValue("friction",t)}get friction(){return this.data.friction}set dragThreshold(t){this._setValue("dragThreshold",t)}get dragThreshold(){return this.data.dragThreshold}set useMouseWheel(t){this._setValue("useMouseWheel",t)}get useMouseWheel(){return this.data.useMouseWheel}set mouseWheelSensitivity(t){this._setValue("mouseWheelSensitivity",t)}get mouseWheelSensitivity(){return this.data.mouseWheelSensitivity}set horizontalScrollbarVisibility(t){this._setValue("horizontalScrollbarVisibility",t)}get horizontalScrollbarVisibility(){return this.data.horizontalScrollbarVisibility}set verticalScrollbarVisibility(t){this._setValue("verticalScrollbarVisibility",t)}get verticalScrollbarVisibility(){return this.data.verticalScrollbarVisibility}set viewportEntity(t){if(this._viewportEntity===t)return;const e="string"==typeof t;this._viewportEntity&&e&&this._viewportEntity.getGuid()===t||(this._viewportEntity&&this._viewportEntityUnsubscribe(),this._viewportEntity=t instanceof o?t:e&&this.system.app.getEntityFromIndex(t)||null,this._viewportEntity&&this._viewportEntitySubscribe(),this._viewportEntity?this.data.viewportEntity=this._viewportEntity.getGuid():e&&t&&(this.data.viewportEntity=t))}get viewportEntity(){return this._viewportEntity}set contentEntity(t){if(this._contentEntity===t)return;const e="string"==typeof t;this._contentEntity&&e&&this._contentEntity.getGuid()===t||(this._contentEntity&&this._contentEntityUnsubscribe(),this._contentEntity=t instanceof o?t:e&&this.system.app.getEntityFromIndex(t)||null,this._contentEntity&&this._contentEntitySubscribe(),this._contentEntity?this.data.contentEntity=this._contentEntity.getGuid():e&&t&&(this.data.contentEntity=t))}get contentEntity(){return this._contentEntity}set horizontalScrollbarEntity(t){if(this._horizontalScrollbarEntity===t)return;const e="string"==typeof t;this._horizontalScrollbarEntity&&e&&this._horizontalScrollbarEntity.getGuid()===t||(this._horizontalScrollbarEntity&&this._horizontalScrollbarEntityUnsubscribe(),this._horizontalScrollbarEntity=t instanceof o?t:e&&this.system.app.getEntityFromIndex(t)||null,this._scrollbarEntities[n]=this._horizontalScrollbarEntity,this._horizontalScrollbarEntity&&this._horizontalScrollbarEntitySubscribe(),this._horizontalScrollbarEntity?this.data.horizontalScrollbarEntity=this._horizontalScrollbarEntity.getGuid():e&&t&&(this.data.horizontalScrollbarEntity=t))}get horizontalScrollbarEntity(){return this._horizontalScrollbarEntity}set verticalScrollbarEntity(t){if(this._verticalScrollbarEntity===t)return;const e="string"==typeof t;this._verticalScrollbarEntity&&e&&this._verticalScrollbarEntity.getGuid()===t||(this._verticalScrollbarEntity&&this._verticalScrollbarEntityUnsubscribe(),this._verticalScrollbarEntity=t instanceof o?t:e&&this.system.app.getEntityFromIndex(t)||null,this._scrollbarEntities[l]=this._verticalScrollbarEntity,this._verticalScrollbarEntity&&this._verticalScrollbarEntitySubscribe(),this._verticalScrollbarEntity?this.data.verticalScrollbarEntity=this._verticalScrollbarEntity.getGuid():e&&t&&(this.data.verticalScrollbarEntity=t))}get verticalScrollbarEntity(){return this._verticalScrollbarEntity}set scroll(t){this._onSetScroll(t.x,t.y)}get scroll(){return this._scroll}_setValue(t,e){const i=this.data,n=i[t];i[t]=e,this.fire("set",t,n,e)}_toggleLifecycleListeners(t){this[t]("set_horizontal",this._onSetHorizontalScrollingEnabled,this),this[t]("set_vertical",this._onSetVerticalScrollingEnabled,this),this.entity[t]("element:add",this._onElementComponentAdd,this)}_toggleElementListeners(t){if(this.entity.element){if("on"===t&&this._hasElementListeners)return;this.entity.element[t]("resize",this._syncAll,this),this.entity.element[t](u,this._onMouseWheel,this),this._hasElementListeners="on"===t}}_onElementComponentAdd(t){this._evtElementRemove=this.entity.element.once("beforeremove",this._onElementComponentRemove,this),this._toggleElementListeners("on")}_onElementComponentRemove(t){var e;null==(e=this._evtElementRemove)||e.off(),this._evtElementRemove=null,this._toggleElementListeners("off")}_viewportEntitySubscribe(){this._evtViewportEntityElementAdd=this._viewportEntity.on("element:add",this._onViewportElementGain,this),this._viewportEntity.element&&this._onViewportElementGain()}_viewportEntityUnsubscribe(){var t,e;null==(t=this._evtViewportEntityElementAdd)||t.off(),this._evtViewportEntityElementAdd=null,null!=(e=this._viewportEntity)&&e.element&&this._onViewportElementLose()}_viewportEntityElementSubscribe(){const t=this._viewportEntity.element;this._evtViewportElementRemove=t.once("beforeremove",this._onViewportElementLose,this),this._evtViewportResize=t.on("resize",this._syncAll,this)}_viewportEntityElementUnsubscribe(){var t,e;null==(t=this._evtViewportElementRemove)||t.off(),this._evtViewportElementRemove=null,null==(e=this._evtViewportResize)||e.off(),this._evtViewportResize=null}_onViewportElementGain(){this._viewportEntityElementSubscribe(),this._syncAll()}_onViewportElementLose(){this._viewportEntityElementUnsubscribe()}_contentEntitySubscribe(){this._evtContentEntityElementAdd=this._contentEntity.on("element:add",this._onContentElementGain,this),this._contentEntity.element&&this._onContentElementGain()}_contentEntityUnsubscribe(){var t,e;null==(t=this._evtContentEntityElementAdd)||t.off(),this._evtContentEntityElementAdd=null,null!=(e=this._contentEntity)&&e.element&&this._onContentElementLose()}_contentEntityElementSubscribe(){const t=this._contentEntity.element;this._evtContentElementRemove=t.once("beforeremove",this._onContentElementLose,this),this._evtContentResize=t.on("resize",this._syncAll,this)}_contentEntityElementUnsubscribe(){var t,e;null==(t=this._evtContentElementRemove)||t.off(),this._evtContentElementRemove=null,null==(e=this._evtContentResize)||e.off(),this._evtContentResize=null}_onContentElementGain(){this._contentEntityElementSubscribe(),this._destroyDragHelper(),this._contentDragHelper=new s(this._contentEntity.element),this._contentDragHelper.on("drag:start",this._onContentDragStart,this),this._contentDragHelper.on("drag:end",this._onContentDragEnd,this),this._contentDragHelper.on("drag:move",this._onContentDragMove,this),this._prevContentSizes[n]=null,this._prevContentSizes[l]=null,this._syncAll()}_onContentElementLose(){this._contentEntityElementUnsubscribe(),this._destroyDragHelper()}_onContentDragStart(){this._contentEntity&&this.enabled&&this.entity.enabled&&this._dragStartPosition.copy(this._contentEntity.getLocalPosition())}_onContentDragEnd(){this._prevContentDragPosition=null,this._enableContentInput()}_onContentDragMove(t){if(this._contentEntity&&this.enabled&&this.entity.enabled&&(this._wasDragged=!0,this._setScrollFromContentPosition(t),this._setVelocityFromContentPositionDelta(t),!this._disabledContentInput)){const e=t.x-this._dragStartPosition.x,i=t.y-this._dragStartPosition.y;(Math.abs(e)>this.dragThreshold||Math.abs(i)>this.dragThreshold)&&this._disableContentInput()}}_horizontalScrollbarEntitySubscribe(){this._evtHorizontalScrollbarAdd=this._horizontalScrollbarEntity.on("scrollbar:add",this._onHorizontalScrollbarGain,this),this._horizontalScrollbarEntity.scrollbar&&this._onHorizontalScrollbarGain()}_verticalScrollbarEntitySubscribe(){this._evtVerticalScrollbarAdd=this._verticalScrollbarEntity.on("scrollbar:add",this._onVerticalScrollbarGain,this),this._verticalScrollbarEntity.scrollbar&&this._onVerticalScrollbarGain()}_horizontalScrollbarEntityUnsubscribe(){var t;null==(t=this._evtHorizontalScrollbarAdd)||t.off(),this._evtHorizontalScrollbarAdd=null,this._horizontalScrollbarEntity.scrollbar&&this._onHorizontalScrollbarLose()}_verticalScrollbarEntityUnsubscribe(){var t;null==(t=this._evtVerticalScrollbarAdd)||t.off(),this._evtVerticalScrollbarAdd=null,this._verticalScrollbarEntity.scrollbar&&this._onVerticalScrollbarLose()}_onSetHorizontalScrollbarValue(t){!this._scrollbarUpdateFlags[n]&&this.enabled&&this.entity.enabled&&this._onSetScroll(t,null)}_onSetVerticalScrollbarValue(t){!this._scrollbarUpdateFlags[l]&&this.enabled&&this.entity.enabled&&this._onSetScroll(null,t)}_onHorizontalScrollbarGain(){var t;const e=null==(t=this._horizontalScrollbarEntity)?void 0:t.scrollbar;this._evtHorizontalScrollbarRemove=e.on("beforeremove",this._onHorizontalScrollbarLose,this),this._evtHorizontalScrollbarValue=e.on("set:value",this._onSetHorizontalScrollbarValue,this),this._syncScrollbarEnabledState(n),this._syncScrollbarPosition(n)}_onVerticalScrollbarGain(){var t;const e=null==(t=this._verticalScrollbarEntity)?void 0:t.scrollbar;this._evtVerticalScrollbarRemove=e.on("beforeremove",this._onVerticalScrollbarLose,this),this._evtVerticalScrollbarValue=e.on("set:value",this._onSetVerticalScrollbarValue,this),this._syncScrollbarEnabledState(l),this._syncScrollbarPosition(l)}_onHorizontalScrollbarLose(){var t,e;null==(t=this._evtHorizontalScrollbarRemove)||t.off(),this._evtHorizontalScrollbarRemove=null,null==(e=this._evtHorizontalScrollbarValue)||e.off(),this._evtHorizontalScrollbarValue=null}_onVerticalScrollbarLose(){var t,e;null==(t=this._evtVerticalScrollbarRemove)||t.off(),this._evtVerticalScrollbarRemove=null,null==(e=this._evtVerticalScrollbarValue)||e.off(),this._evtVerticalScrollbarValue=null}_onSetHorizontalScrollingEnabled(){this._syncScrollbarEnabledState(n)}_onSetVerticalScrollingEnabled(){this._syncScrollbarEnabledState(l)}_onSetScroll(t,e,i){!1!==i&&this._velocity.set(0,0,0);const o=this._updateAxis(t,"x",n),s=this._updateAxis(e,"y",l);(o||s)&&this.fire("set:scroll",this._scroll)}_updateAxis(t,e,i){const n=null!==t&&Math.abs(t-this._scroll[e])>1e-5;return(n||this._isDragging()||0===t)&&(this._scroll[e]=this._determineNewScrollValue(t,e,i),this._syncContentPosition(i),this._syncScrollbarPosition(i)),n}_determineNewScrollValue(e,i,n){if(!this._getScrollingEnabled(n))return this._scroll[i];switch(this.scrollMode){case h:return t.clamp(e,0,this._getMaxScrollValue(n));case a:return this._setVelocityFromOvershoot(e,i,n),e;case r:return e;default:return console.warn(`Unhandled scroll mode:${this.scrollMode}`),e}}_syncAll(){this._syncContentPosition(n),this._syncContentPosition(l),this._syncScrollbarPosition(n),this._syncScrollbarPosition(l),this._syncScrollbarEnabledState(n),this._syncScrollbarEnabledState(l)}_syncContentPosition(e){if(!this._contentEntity)return;const i=this._getAxis(e),n=this._getSign(e),l=this._prevContentSizes[e],o=this._getContentSize(e);if(null!==l&&Math.abs(l-o)>1e-4){const n=this._getMaxOffset(e,l),s=this._getMaxOffset(e,o);this._scroll[i]=0===s?1:t.clamp(this._scroll[i]*n/s,0,1)}const s=this._scroll[i]*this._getMaxOffset(e),r=this._contentEntity.getLocalPosition();r[i]=s*n,this._contentEntity.setLocalPosition(r),this._prevContentSizes[e]=o}_syncScrollbarPosition(t){const e=this._scrollbarEntities[t];if(null==e||!e.scrollbar)return;const i=this._getAxis(t);this._scrollbarUpdateFlags[t]=!0,e.scrollbar.value=this._scroll[i],e.scrollbar.handleSize=this._getScrollbarHandleSize(i,t),this._scrollbarUpdateFlags[t]=!1}_syncScrollbarEnabledState(t){const e=this._scrollbarEntities[t];if(!e)return;const i=this._getScrollingEnabled(t),n=this._getScrollbarVisibility(t);switch(n){case _:return void(e.enabled=i);case c:return void(e.enabled=i&&this._contentIsLargerThanViewport(t));default:console.warn(`Unhandled scrollbar visibility:${n}`),e.enabled=i}}_contentIsLargerThanViewport(t){return this._getContentSize(t)>this._getViewportSize(t)}_contentPositionToScrollValue(t){const e=this._getMaxOffset(n),i=this._getMaxOffset(l);return y.x=0===e?0:t.x/e,y.y=0===i?0:t.y/-i,y}_getMaxOffset(t,e){e=void 0===e?this._getContentSize(t):e;const i=this._getViewportSize(t);return e<i?-this._getViewportSize(t):i-e}_getMaxScrollValue(t){return this._contentIsLargerThanViewport(t)?1:0}_getScrollbarHandleSize(t,e){const i=this._getViewportSize(e),n=this._getContentSize(e);if(Math.abs(n)<.001)return 1;const l=Math.min(i/n,1),o=this._toOvershoot(this._scroll[t],e);return 0===o?l:l/(1+Math.abs(o))}_getViewportSize(t){return this._getSize(t,this._viewportEntity)}_getContentSize(t){return this._getSize(t,this._contentEntity)}_getSize(t,e){return null!=e&&e.element?e.element[this._getCalculatedDimension(t)]:0}_getScrollingEnabled(t){return t===n?this.horizontal:t===l?this.vertical:void 0}_getScrollbarVisibility(t){return t===n?this.horizontalScrollbarVisibility:t===l?this.verticalScrollbarVisibility:void 0}_getSign(t){return t===n?1:-1}_getAxis(t){return t===n?"x":"y"}_getCalculatedDimension(t){return t===n?"calculatedWidth":"calculatedHeight"}_destroyDragHelper(){this._contentDragHelper&&this._contentDragHelper.destroy()}onUpdate(){this._contentEntity&&(this._updateVelocity(),this._syncScrollbarEnabledState(n),this._syncScrollbarEnabledState(l))}_updateVelocity(){if(!this._isDragging()){if(this.scrollMode===a&&(this._hasOvershoot("x",n)&&this._setVelocityFromOvershoot(this.scroll.x,"x",n),this._hasOvershoot("y",l)&&this._setVelocityFromOvershoot(this.scroll.y,"y",l)),Math.abs(this._velocity.x)>1e-4||Math.abs(this._velocity.y)>1e-4){const t=this._contentEntity.getLocalPosition();t.x+=this._velocity.x,t.y+=this._velocity.y,this._contentEntity.setLocalPosition(t),this._setScrollFromContentPosition(t)}this._velocity.x*=1-this.friction,this._velocity.y*=1-this.friction}}_hasOvershoot(t,e){return Math.abs(this._toOvershoot(this.scroll[t],e))>.001}_toOvershoot(t,e){const i=this._getMaxScrollValue(e);return t<0?t:t>i?t-i:0}_setVelocityFromOvershoot(t,e,i){const n=this._toOvershoot(t,i)*this._getMaxOffset(i)*this._getSign(i);Math.abs(n)>0&&(this._velocity[e]=-n/(50*this.bounceAmount+1))}_setVelocityFromContentPositionDelta(t){this._prevContentDragPosition?(this._velocity.sub2(t,this._prevContentDragPosition),this._prevContentDragPosition.copy(t)):(this._velocity.set(0,0,0),this._prevContentDragPosition=t.clone())}_setScrollFromContentPosition(t){let e=this._contentPositionToScrollValue(t);this._isDragging()&&(e=this._applyScrollValueTension(e)),this._onSetScroll(e.x,e.y,!1)}_applyScrollValueTension(t){let e=this._getMaxScrollValue(n),i=this._toOvershoot(t.x,n);return i>0?t.x=e+1*Math.log10(1+i):i<0&&(t.x=-1*Math.log10(1-i)),e=this._getMaxScrollValue(l),i=this._toOvershoot(t.y,l),i>0?t.y=e+1*Math.log10(1+i):i<0&&(t.y=-1*Math.log10(1-i)),t}_isDragging(){return this._contentDragHelper&&this._contentDragHelper.isDragging}_setScrollbarComponentsEnabled(t){var e,i;null!=(e=this._horizontalScrollbarEntity)&&e.scrollbar&&(this._horizontalScrollbarEntity.scrollbar.enabled=t),null!=(i=this._verticalScrollbarEntity)&&i.scrollbar&&(this._verticalScrollbarEntity.scrollbar.enabled=t)}_setContentDraggingEnabled(t){this._contentDragHelper&&(this._contentDragHelper.enabled=t)}_onMouseWheel(i){var o;if(!this.useMouseWheel||null==(o=this._contentEntity)||!o.element)return;const s=i.event,r=s.deltaX/this._contentEntity.element.calculatedWidth*this.mouseWheelSensitivity.x,a=s.deltaY/this._contentEntity.element.calculatedHeight*this.mouseWheelSensitivity.y,h=t.clamp(this._scroll.x+r,0,this._getMaxScrollValue(n)),c=t.clamp(this._scroll.y+a,0,this._getMaxScrollValue(l));this.scroll=new e(h,c)}_enableContentInput(){for(;this._disabledContentInputEntities.length;){const t=this._disabledContentInputEntities.pop();t.element&&(t.element.useInput=!0)}this._disabledContentInput=!1}_disableContentInput(){const t=e=>{e.element&&e.element.useInput&&(this._disabledContentInputEntities.push(e),e.element.useInput=!1);const i=e.children;for(let e=0,n=i.length;e<n;e++)t(i[e])};if(this._contentEntity){const e=this._contentEntity.children;for(let i=0,n=e.length;i<n;i++)t(e[i])}this._disabledContentInput=!0}onEnable(){this._setScrollbarComponentsEnabled(!0),this._setContentDraggingEnabled(!0),this._syncAll()}onDisable(){this._setScrollbarComponentsEnabled(!1),this._setContentDraggingEnabled(!1)}onRemove(){this._toggleLifecycleListeners("off"),this._toggleElementListeners("off"),this._destroyDragHelper()}resolveDuplicatedEntityReferenceProperties(t,e){t.viewportEntity&&(this.viewportEntity=e[t.viewportEntity.getGuid()]),t.contentEntity&&(this.contentEntity=e[t.contentEntity.getGuid()]),t.horizontalScrollbarEntity&&(this.horizontalScrollbarEntity=e[t.horizontalScrollbarEntity.getGuid()]),t.verticalScrollbarEntity&&(this.verticalScrollbarEntity=e[t.verticalScrollbarEntity.getGuid()])}}E.EVENT_SETSCROLL="set:scroll";export{E as ScrollViewComponent};