UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

767 lines (764 loc) 28.3 kB
import { math } from '../../../core/math/math.js'; import { Vec2 } from '../../../core/math/vec2.js'; import { Vec3 } from '../../../core/math/vec3.js'; import { ORIENTATION_HORIZONTAL, ORIENTATION_VERTICAL } from '../../../scene/constants.js'; import { GraphNode } from '../../../scene/graph-node.js'; import { ElementDragHelper } from '../element/element-drag-helper.js'; import { SCROLL_MODE_INFINITE, SCROLL_MODE_BOUNCE, SCROLL_MODE_CLAMP, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED, SCROLLBAR_VISIBILITY_SHOW_ALWAYS } from './constants.js'; import { Component } from '../component.js'; const _tempScrollValue = new Vec2(); class ScrollViewComponent extends Component { static{ this.EVENT_SETSCROLL = 'set:scroll'; } constructor(system, entity){ super(system, entity), 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[ORIENTATION_HORIZONTAL] = null; this._prevContentSizes[ORIENTATION_VERTICAL] = null; this._scroll = new Vec2(); this._velocity = new Vec3(); this._dragStartPosition = new Vec3(); this._disabledContentInput = false; this._disabledContentInputEntities = []; this._toggleLifecycleListeners('on'); this._toggleElementListeners('on'); } get data() { const record = this.system.store[this.entity.getGuid()]; return record ? record.data : null; } set enabled(arg) { this._setValue('enabled', arg); } get enabled() { return this.data.enabled; } set horizontal(arg) { this._setValue('horizontal', arg); } get horizontal() { return this.data.horizontal; } set vertical(arg) { this._setValue('vertical', arg); } get vertical() { return this.data.vertical; } set scrollMode(arg) { this._setValue('scrollMode', arg); } get scrollMode() { return this.data.scrollMode; } set bounceAmount(arg) { this._setValue('bounceAmount', arg); } get bounceAmount() { return this.data.bounceAmount; } set friction(arg) { this._setValue('friction', arg); } get friction() { return this.data.friction; } set dragThreshold(arg) { this._setValue('dragThreshold', arg); } get dragThreshold() { return this.data.dragThreshold; } set useMouseWheel(arg) { this._setValue('useMouseWheel', arg); } get useMouseWheel() { return this.data.useMouseWheel; } set mouseWheelSensitivity(arg) { this._setValue('mouseWheelSensitivity', arg); } get mouseWheelSensitivity() { return this.data.mouseWheelSensitivity; } set horizontalScrollbarVisibility(arg) { this._setValue('horizontalScrollbarVisibility', arg); } get horizontalScrollbarVisibility() { return this.data.horizontalScrollbarVisibility; } set verticalScrollbarVisibility(arg) { this._setValue('verticalScrollbarVisibility', arg); } get verticalScrollbarVisibility() { return this.data.verticalScrollbarVisibility; } set viewportEntity(arg) { if (this._viewportEntity === arg) { return; } const isString = typeof arg === 'string'; if (this._viewportEntity && isString && this._viewportEntity.getGuid() === arg) { return; } if (this._viewportEntity) { this._viewportEntityUnsubscribe(); } if (arg instanceof GraphNode) { this._viewportEntity = arg; } else if (isString) { this._viewportEntity = this.system.app.getEntityFromIndex(arg) || null; } else { this._viewportEntity = null; } if (this._viewportEntity) { this._viewportEntitySubscribe(); } if (this._viewportEntity) { this.data.viewportEntity = this._viewportEntity.getGuid(); } else if (isString && arg) { this.data.viewportEntity = arg; } } get viewportEntity() { return this._viewportEntity; } set contentEntity(arg) { if (this._contentEntity === arg) { return; } const isString = typeof arg === 'string'; if (this._contentEntity && isString && this._contentEntity.getGuid() === arg) { return; } if (this._contentEntity) { this._contentEntityUnsubscribe(); } if (arg instanceof GraphNode) { this._contentEntity = arg; } else if (isString) { this._contentEntity = this.system.app.getEntityFromIndex(arg) || null; } else { this._contentEntity = null; } if (this._contentEntity) { this._contentEntitySubscribe(); } if (this._contentEntity) { this.data.contentEntity = this._contentEntity.getGuid(); } else if (isString && arg) { this.data.contentEntity = arg; } } get contentEntity() { return this._contentEntity; } set horizontalScrollbarEntity(arg) { if (this._horizontalScrollbarEntity === arg) { return; } const isString = typeof arg === 'string'; if (this._horizontalScrollbarEntity && isString && this._horizontalScrollbarEntity.getGuid() === arg) { return; } if (this._horizontalScrollbarEntity) { this._horizontalScrollbarEntityUnsubscribe(); } if (arg instanceof GraphNode) { this._horizontalScrollbarEntity = arg; } else if (isString) { this._horizontalScrollbarEntity = this.system.app.getEntityFromIndex(arg) || null; } else { this._horizontalScrollbarEntity = null; } this._scrollbarEntities[ORIENTATION_HORIZONTAL] = this._horizontalScrollbarEntity; if (this._horizontalScrollbarEntity) { this._horizontalScrollbarEntitySubscribe(); } if (this._horizontalScrollbarEntity) { this.data.horizontalScrollbarEntity = this._horizontalScrollbarEntity.getGuid(); } else if (isString && arg) { this.data.horizontalScrollbarEntity = arg; } } get horizontalScrollbarEntity() { return this._horizontalScrollbarEntity; } set verticalScrollbarEntity(arg) { if (this._verticalScrollbarEntity === arg) { return; } const isString = typeof arg === 'string'; if (this._verticalScrollbarEntity && isString && this._verticalScrollbarEntity.getGuid() === arg) { return; } if (this._verticalScrollbarEntity) { this._verticalScrollbarEntityUnsubscribe(); } if (arg instanceof GraphNode) { this._verticalScrollbarEntity = arg; } else if (isString) { this._verticalScrollbarEntity = this.system.app.getEntityFromIndex(arg) || null; } else { this._verticalScrollbarEntity = null; } this._scrollbarEntities[ORIENTATION_VERTICAL] = this._verticalScrollbarEntity; if (this._verticalScrollbarEntity) { this._verticalScrollbarEntitySubscribe(); } if (this._verticalScrollbarEntity) { this.data.verticalScrollbarEntity = this._verticalScrollbarEntity.getGuid(); } else if (isString && arg) { this.data.verticalScrollbarEntity = arg; } } get verticalScrollbarEntity() { return this._verticalScrollbarEntity; } set scroll(value) { this._onSetScroll(value.x, value.y); } get scroll() { return this._scroll; } _setValue(name, value) { const data = this.data; const oldValue = data[name]; data[name] = value; this.fire('set', name, oldValue, value); } _toggleLifecycleListeners(onOrOff) { this[onOrOff]('set_horizontal', this._onSetHorizontalScrollingEnabled, this); this[onOrOff]('set_vertical', this._onSetVerticalScrollingEnabled, this); this.entity[onOrOff]('element:add', this._onElementComponentAdd, this); } _toggleElementListeners(onOrOff) { if (this.entity.element) { if (onOrOff === 'on' && this._hasElementListeners) { return; } this.entity.element[onOrOff]('resize', this._syncAll, this); this.entity.element[onOrOff]('mousewheel', this._onMouseWheel, this); this._hasElementListeners = onOrOff === 'on'; } } _onElementComponentAdd(entity) { this._evtElementRemove = this.entity.element.once('beforeremove', this._onElementComponentRemove, this); this._toggleElementListeners('on'); } _onElementComponentRemove(entity) { this._evtElementRemove?.off(); this._evtElementRemove = null; this._toggleElementListeners('off'); } _viewportEntitySubscribe() { this._evtViewportEntityElementAdd = this._viewportEntity.on('element:add', this._onViewportElementGain, this); if (this._viewportEntity.element) { this._onViewportElementGain(); } } _viewportEntityUnsubscribe() { this._evtViewportEntityElementAdd?.off(); this._evtViewportEntityElementAdd = null; if (this._viewportEntity?.element) { this._onViewportElementLose(); } } _viewportEntityElementSubscribe() { const element = this._viewportEntity.element; this._evtViewportElementRemove = element.once('beforeremove', this._onViewportElementLose, this); this._evtViewportResize = element.on('resize', this._syncAll, this); } _viewportEntityElementUnsubscribe() { this._evtViewportElementRemove?.off(); this._evtViewportElementRemove = null; this._evtViewportResize?.off(); this._evtViewportResize = null; } _onViewportElementGain() { this._viewportEntityElementSubscribe(); this._syncAll(); } _onViewportElementLose() { this._viewportEntityElementUnsubscribe(); } _contentEntitySubscribe() { this._evtContentEntityElementAdd = this._contentEntity.on('element:add', this._onContentElementGain, this); if (this._contentEntity.element) { this._onContentElementGain(); } } _contentEntityUnsubscribe() { this._evtContentEntityElementAdd?.off(); this._evtContentEntityElementAdd = null; if (this._contentEntity?.element) { this._onContentElementLose(); } } _contentEntityElementSubscribe() { const element = this._contentEntity.element; this._evtContentElementRemove = element.once('beforeremove', this._onContentElementLose, this); this._evtContentResize = element.on('resize', this._syncAll, this); } _contentEntityElementUnsubscribe() { this._evtContentElementRemove?.off(); this._evtContentElementRemove = null; this._evtContentResize?.off(); this._evtContentResize = null; } _onContentElementGain() { this._contentEntityElementSubscribe(); this._destroyDragHelper(); this._contentDragHelper = new ElementDragHelper(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[ORIENTATION_HORIZONTAL] = null; this._prevContentSizes[ORIENTATION_VERTICAL] = null; this._syncAll(); } _onContentElementLose() { this._contentEntityElementUnsubscribe(); this._destroyDragHelper(); } _onContentDragStart() { if (this._contentEntity && this.enabled && this.entity.enabled) { this._dragStartPosition.copy(this._contentEntity.getLocalPosition()); } } _onContentDragEnd() { this._prevContentDragPosition = null; this._enableContentInput(); } _onContentDragMove(position) { if (this._contentEntity && this.enabled && this.entity.enabled) { this._wasDragged = true; this._setScrollFromContentPosition(position); this._setVelocityFromContentPositionDelta(position); if (!this._disabledContentInput) { const dx = position.x - this._dragStartPosition.x; const dy = position.y - this._dragStartPosition.y; if (Math.abs(dx) > this.dragThreshold || Math.abs(dy) > this.dragThreshold) { this._disableContentInput(); } } } } _horizontalScrollbarEntitySubscribe() { this._evtHorizontalScrollbarAdd = this._horizontalScrollbarEntity.on('scrollbar:add', this._onHorizontalScrollbarGain, this); if (this._horizontalScrollbarEntity.scrollbar) { this._onHorizontalScrollbarGain(); } } _verticalScrollbarEntitySubscribe() { this._evtVerticalScrollbarAdd = this._verticalScrollbarEntity.on('scrollbar:add', this._onVerticalScrollbarGain, this); if (this._verticalScrollbarEntity.scrollbar) { this._onVerticalScrollbarGain(); } } _horizontalScrollbarEntityUnsubscribe() { this._evtHorizontalScrollbarAdd?.off(); this._evtHorizontalScrollbarAdd = null; if (this._horizontalScrollbarEntity.scrollbar) { this._onHorizontalScrollbarLose(); } } _verticalScrollbarEntityUnsubscribe() { this._evtVerticalScrollbarAdd?.off(); this._evtVerticalScrollbarAdd = null; if (this._verticalScrollbarEntity.scrollbar) { this._onVerticalScrollbarLose(); } } _onSetHorizontalScrollbarValue(scrollValueX) { if (!this._scrollbarUpdateFlags[ORIENTATION_HORIZONTAL] && this.enabled && this.entity.enabled) { this._onSetScroll(scrollValueX, null); } } _onSetVerticalScrollbarValue(scrollValueY) { if (!this._scrollbarUpdateFlags[ORIENTATION_VERTICAL] && this.enabled && this.entity.enabled) { this._onSetScroll(null, scrollValueY); } } _onHorizontalScrollbarGain() { const scrollbar = this._horizontalScrollbarEntity?.scrollbar; this._evtHorizontalScrollbarRemove = scrollbar.on('beforeremove', this._onHorizontalScrollbarLose, this); this._evtHorizontalScrollbarValue = scrollbar.on('set:value', this._onSetHorizontalScrollbarValue, this); this._syncScrollbarEnabledState(ORIENTATION_HORIZONTAL); this._syncScrollbarPosition(ORIENTATION_HORIZONTAL); } _onVerticalScrollbarGain() { const scrollbar = this._verticalScrollbarEntity?.scrollbar; this._evtVerticalScrollbarRemove = scrollbar.on('beforeremove', this._onVerticalScrollbarLose, this); this._evtVerticalScrollbarValue = scrollbar.on('set:value', this._onSetVerticalScrollbarValue, this); this._syncScrollbarEnabledState(ORIENTATION_VERTICAL); this._syncScrollbarPosition(ORIENTATION_VERTICAL); } _onHorizontalScrollbarLose() { this._evtHorizontalScrollbarRemove?.off(); this._evtHorizontalScrollbarRemove = null; this._evtHorizontalScrollbarValue?.off(); this._evtHorizontalScrollbarValue = null; } _onVerticalScrollbarLose() { this._evtVerticalScrollbarRemove?.off(); this._evtVerticalScrollbarRemove = null; this._evtVerticalScrollbarValue?.off(); this._evtVerticalScrollbarValue = null; } _onSetHorizontalScrollingEnabled() { this._syncScrollbarEnabledState(ORIENTATION_HORIZONTAL); } _onSetVerticalScrollingEnabled() { this._syncScrollbarEnabledState(ORIENTATION_VERTICAL); } _onSetScroll(x, y, resetVelocity) { if (resetVelocity !== false) { this._velocity.set(0, 0, 0); } const xChanged = this._updateAxis(x, 'x', ORIENTATION_HORIZONTAL); const yChanged = this._updateAxis(y, 'y', ORIENTATION_VERTICAL); if (xChanged || yChanged) { this.fire('set:scroll', this._scroll); } } _updateAxis(scrollValue, axis, orientation) { const hasChanged = scrollValue !== null && Math.abs(scrollValue - this._scroll[axis]) > 1e-5; if (hasChanged || this._isDragging() || scrollValue === 0) { this._scroll[axis] = this._determineNewScrollValue(scrollValue, axis, orientation); this._syncContentPosition(orientation); this._syncScrollbarPosition(orientation); } return hasChanged; } _determineNewScrollValue(scrollValue, axis, orientation) { if (!this._getScrollingEnabled(orientation)) { return this._scroll[axis]; } switch(this.scrollMode){ case SCROLL_MODE_CLAMP: return math.clamp(scrollValue, 0, this._getMaxScrollValue(orientation)); case SCROLL_MODE_BOUNCE: this._setVelocityFromOvershoot(scrollValue, axis, orientation); return scrollValue; case SCROLL_MODE_INFINITE: return scrollValue; default: console.warn(`Unhandled scroll mode:${this.scrollMode}`); return scrollValue; } } _syncAll() { this._syncContentPosition(ORIENTATION_HORIZONTAL); this._syncContentPosition(ORIENTATION_VERTICAL); this._syncScrollbarPosition(ORIENTATION_HORIZONTAL); this._syncScrollbarPosition(ORIENTATION_VERTICAL); this._syncScrollbarEnabledState(ORIENTATION_HORIZONTAL); this._syncScrollbarEnabledState(ORIENTATION_VERTICAL); } _syncContentPosition(orientation) { if (!this._contentEntity) { return; } const axis = this._getAxis(orientation); const sign = this._getSign(orientation); const prevContentSize = this._prevContentSizes[orientation]; const currContentSize = this._getContentSize(orientation); if (prevContentSize !== null && Math.abs(prevContentSize - currContentSize) > 1e-4) { const prevMaxOffset = this._getMaxOffset(orientation, prevContentSize); const currMaxOffset = this._getMaxOffset(orientation, currContentSize); if (currMaxOffset === 0) { this._scroll[axis] = 1; } else { this._scroll[axis] = math.clamp(this._scroll[axis] * prevMaxOffset / currMaxOffset, 0, 1); } } const offset = this._scroll[axis] * this._getMaxOffset(orientation); const contentPosition = this._contentEntity.getLocalPosition(); contentPosition[axis] = offset * sign; this._contentEntity.setLocalPosition(contentPosition); this._prevContentSizes[orientation] = currContentSize; } _syncScrollbarPosition(orientation) { const scrollbarEntity = this._scrollbarEntities[orientation]; if (!scrollbarEntity?.scrollbar) { return; } const axis = this._getAxis(orientation); this._scrollbarUpdateFlags[orientation] = true; scrollbarEntity.scrollbar.value = this._scroll[axis]; scrollbarEntity.scrollbar.handleSize = this._getScrollbarHandleSize(axis, orientation); this._scrollbarUpdateFlags[orientation] = false; } _syncScrollbarEnabledState(orientation) { const entity = this._scrollbarEntities[orientation]; if (!entity) { return; } const isScrollingEnabled = this._getScrollingEnabled(orientation); const requestedVisibility = this._getScrollbarVisibility(orientation); switch(requestedVisibility){ case SCROLLBAR_VISIBILITY_SHOW_ALWAYS: entity.enabled = isScrollingEnabled; return; case SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED: entity.enabled = isScrollingEnabled && this._contentIsLargerThanViewport(orientation); return; default: console.warn(`Unhandled scrollbar visibility:${requestedVisibility}`); entity.enabled = isScrollingEnabled; } } _contentIsLargerThanViewport(orientation) { return this._getContentSize(orientation) > this._getViewportSize(orientation); } _contentPositionToScrollValue(contentPosition) { const maxOffsetH = this._getMaxOffset(ORIENTATION_HORIZONTAL); const maxOffsetV = this._getMaxOffset(ORIENTATION_VERTICAL); if (maxOffsetH === 0) { _tempScrollValue.x = 0; } else { _tempScrollValue.x = contentPosition.x / maxOffsetH; } if (maxOffsetV === 0) { _tempScrollValue.y = 0; } else { _tempScrollValue.y = contentPosition.y / -maxOffsetV; } return _tempScrollValue; } _getMaxOffset(orientation, contentSize) { contentSize = contentSize === undefined ? this._getContentSize(orientation) : contentSize; const viewportSize = this._getViewportSize(orientation); if (contentSize < viewportSize) { return -this._getViewportSize(orientation); } return viewportSize - contentSize; } _getMaxScrollValue(orientation) { return this._contentIsLargerThanViewport(orientation) ? 1 : 0; } _getScrollbarHandleSize(axis, orientation) { const viewportSize = this._getViewportSize(orientation); const contentSize = this._getContentSize(orientation); if (Math.abs(contentSize) < 0.001) { return 1; } const handleSize = Math.min(viewportSize / contentSize, 1); const overshoot = this._toOvershoot(this._scroll[axis], orientation); if (overshoot === 0) { return handleSize; } return handleSize / (1 + Math.abs(overshoot)); } _getViewportSize(orientation) { return this._getSize(orientation, this._viewportEntity); } _getContentSize(orientation) { return this._getSize(orientation, this._contentEntity); } _getSize(orientation, entity) { if (entity?.element) { return entity.element[this._getCalculatedDimension(orientation)]; } return 0; } _getScrollingEnabled(orientation) { if (orientation === ORIENTATION_HORIZONTAL) { return this.horizontal; } else if (orientation === ORIENTATION_VERTICAL) { return this.vertical; } return undefined; } _getScrollbarVisibility(orientation) { if (orientation === ORIENTATION_HORIZONTAL) { return this.horizontalScrollbarVisibility; } else if (orientation === ORIENTATION_VERTICAL) { return this.verticalScrollbarVisibility; } return undefined; } _getSign(orientation) { return orientation === ORIENTATION_HORIZONTAL ? 1 : -1; } _getAxis(orientation) { return orientation === ORIENTATION_HORIZONTAL ? 'x' : 'y'; } _getCalculatedDimension(orientation) { return orientation === ORIENTATION_HORIZONTAL ? 'calculatedWidth' : 'calculatedHeight'; } _destroyDragHelper() { if (this._contentDragHelper) { this._contentDragHelper.destroy(); } } onUpdate() { if (this._contentEntity) { this._updateVelocity(); this._syncScrollbarEnabledState(ORIENTATION_HORIZONTAL); this._syncScrollbarEnabledState(ORIENTATION_VERTICAL); } } _updateVelocity() { if (!this._isDragging()) { if (this.scrollMode === SCROLL_MODE_BOUNCE) { if (this._hasOvershoot('x', ORIENTATION_HORIZONTAL)) { this._setVelocityFromOvershoot(this.scroll.x, 'x', ORIENTATION_HORIZONTAL); } if (this._hasOvershoot('y', ORIENTATION_VERTICAL)) { this._setVelocityFromOvershoot(this.scroll.y, 'y', ORIENTATION_VERTICAL); } } if (Math.abs(this._velocity.x) > 1e-4 || Math.abs(this._velocity.y) > 1e-4) { const position = this._contentEntity.getLocalPosition(); position.x += this._velocity.x; position.y += this._velocity.y; this._contentEntity.setLocalPosition(position); this._setScrollFromContentPosition(position); } this._velocity.x *= 1 - this.friction; this._velocity.y *= 1 - this.friction; } } _hasOvershoot(axis, orientation) { return Math.abs(this._toOvershoot(this.scroll[axis], orientation)) > 0.001; } _toOvershoot(scrollValue, orientation) { const maxScrollValue = this._getMaxScrollValue(orientation); if (scrollValue < 0) { return scrollValue; } else if (scrollValue > maxScrollValue) { return scrollValue - maxScrollValue; } return 0; } _setVelocityFromOvershoot(scrollValue, axis, orientation) { const overshootValue = this._toOvershoot(scrollValue, orientation); const overshootPixels = overshootValue * this._getMaxOffset(orientation) * this._getSign(orientation); if (Math.abs(overshootPixels) > 0) { this._velocity[axis] = -overshootPixels / (this.bounceAmount * 50 + 1); } } _setVelocityFromContentPositionDelta(position) { if (this._prevContentDragPosition) { this._velocity.sub2(position, this._prevContentDragPosition); this._prevContentDragPosition.copy(position); } else { this._velocity.set(0, 0, 0); this._prevContentDragPosition = position.clone(); } } _setScrollFromContentPosition(position) { let scrollValue = this._contentPositionToScrollValue(position); if (this._isDragging()) { scrollValue = this._applyScrollValueTension(scrollValue); } this._onSetScroll(scrollValue.x, scrollValue.y, false); } _applyScrollValueTension(scrollValue) { const factor = 1; let max = this._getMaxScrollValue(ORIENTATION_HORIZONTAL); let overshoot = this._toOvershoot(scrollValue.x, ORIENTATION_HORIZONTAL); if (overshoot > 0) { scrollValue.x = max + factor * Math.log10(1 + overshoot); } else if (overshoot < 0) { scrollValue.x = -1 * Math.log10(1 - overshoot); } max = this._getMaxScrollValue(ORIENTATION_VERTICAL); overshoot = this._toOvershoot(scrollValue.y, ORIENTATION_VERTICAL); if (overshoot > 0) { scrollValue.y = max + factor * Math.log10(1 + overshoot); } else if (overshoot < 0) { scrollValue.y = -1 * Math.log10(1 - overshoot); } return scrollValue; } _isDragging() { return this._contentDragHelper && this._contentDragHelper.isDragging; } _setScrollbarComponentsEnabled(enabled) { if (this._horizontalScrollbarEntity?.scrollbar) { this._horizontalScrollbarEntity.scrollbar.enabled = enabled; } if (this._verticalScrollbarEntity?.scrollbar) { this._verticalScrollbarEntity.scrollbar.enabled = enabled; } } _setContentDraggingEnabled(enabled) { if (this._contentDragHelper) { this._contentDragHelper.enabled = enabled; } } _onMouseWheel(event) { if (!this.useMouseWheel || !this._contentEntity?.element) { return; } const wheelEvent = event.event; const normalizedDeltaX = wheelEvent.deltaX / this._contentEntity.element.calculatedWidth * this.mouseWheelSensitivity.x; const normalizedDeltaY = wheelEvent.deltaY / this._contentEntity.element.calculatedHeight * this.mouseWheelSensitivity.y; const scrollX = math.clamp(this._scroll.x + normalizedDeltaX, 0, this._getMaxScrollValue(ORIENTATION_HORIZONTAL)); const scrollY = math.clamp(this._scroll.y + normalizedDeltaY, 0, this._getMaxScrollValue(ORIENTATION_VERTICAL)); this.scroll = new Vec2(scrollX, scrollY); } _enableContentInput() { while(this._disabledContentInputEntities.length){ const e = this._disabledContentInputEntities.pop(); if (e.element) { e.element.useInput = true; } } this._disabledContentInput = false; } _disableContentInput() { const _disableInput = (e)=>{ if (e.element && e.element.useInput) { this._disabledContentInputEntities.push(e); e.element.useInput = false; } const children = e.children; for(let i = 0, l = children.length; i < l; i++){ _disableInput(children[i]); } }; if (this._contentEntity) { const children = this._contentEntity.children; for(let i = 0, l = children.length; i < l; i++){ _disableInput(children[i]); } } this._disabledContentInput = true; } onEnable() { this._setScrollbarComponentsEnabled(true); this._setContentDraggingEnabled(true); this._syncAll(); } onDisable() { this._setScrollbarComponentsEnabled(false); this._setContentDraggingEnabled(false); } onRemove() { this._toggleLifecycleListeners('off'); this._toggleElementListeners('off'); this._destroyDragHelper(); } resolveDuplicatedEntityReferenceProperties(oldScrollView, duplicatedIdsMap) { if (oldScrollView.viewportEntity) { this.viewportEntity = duplicatedIdsMap[oldScrollView.viewportEntity.getGuid()]; } if (oldScrollView.contentEntity) { this.contentEntity = duplicatedIdsMap[oldScrollView.contentEntity.getGuid()]; } if (oldScrollView.horizontalScrollbarEntity) { this.horizontalScrollbarEntity = duplicatedIdsMap[oldScrollView.horizontalScrollbarEntity.getGuid()]; } if (oldScrollView.verticalScrollbarEntity) { this.verticalScrollbarEntity = duplicatedIdsMap[oldScrollView.verticalScrollbarEntity.getGuid()]; } } } export { ScrollViewComponent };