UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

221 lines (218 loc) 7.05 kB
import { math } from '../../../core/math/math.js'; import { ORIENTATION_HORIZONTAL } from '../../../scene/constants.js'; import { GraphNode } from '../../../scene/graph-node.js'; import { Component } from '../component.js'; import { ElementDragHelper } from '../element/element-drag-helper.js'; class ScrollbarComponent extends Component { static{ this.EVENT_SETVALUE = 'set:value'; } constructor(system, entity){ super(system, entity), this._handleEntity = null, this._evtHandleEntityElementAdd = null, this._evtHandleEntityChanges = []; this._toggleLifecycleListeners('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 orientation(arg) { this._setValue('orientation', arg); } get orientation() { return this.data.orientation; } set value(arg) { this._setValue('value', arg); } get value() { return this.data.value; } set handleSize(arg) { this._setValue('handleSize', arg); } get handleSize() { return this.data.handleSize; } set handleEntity(arg) { if (this._handleEntity === arg) { return; } const isString = typeof arg === 'string'; if (this._handleEntity && isString && this._handleEntity.getGuid() === arg) { return; } if (this._handleEntity) { this._handleEntityUnsubscribe(); } if (arg instanceof GraphNode) { this._handleEntity = arg; } else if (isString) { this._handleEntity = this.system.app.getEntityFromIndex(arg) || null; } else { this._handleEntity = null; } if (this._handleEntity) { this._handleEntitySubscribe(); } if (this._handleEntity) { this.data.handleEntity = this._handleEntity.getGuid(); } else if (isString && arg) { this.data.handleEntity = arg; } } get handleEntity() { return this._handleEntity; } _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_value', this._onSetValue, this); this[onOrOff]('set_handleSize', this._onSetHandleSize, this); this[onOrOff]('set_orientation', this._onSetOrientation, this); } _handleEntitySubscribe() { this._evtHandleEntityElementAdd = this._handleEntity.on('element:add', this._onHandleElementGain, this); if (this._handleEntity.element) { this._onHandleElementGain(); } } _handleEntityUnsubscribe() { this._evtHandleEntityElementAdd?.off(); this._evtHandleEntityElementAdd = null; if (this._handleEntity?.element) { this._onHandleElementLose(); } } _handleEntityElementSubscribe() { const element = this._handleEntity.element; const handles = this._evtHandleEntityChanges; handles.push(element.once('beforeremove', this._onHandleElementLose, this)); handles.push(element.on('set:anchor', this._onSetHandleAlignment, this)); handles.push(element.on('set:margin', this._onSetHandleAlignment, this)); handles.push(element.on('set:pivot', this._onSetHandleAlignment, this)); } _handleEntityElementUnsubscribe() { for(let i = 0; i < this._evtHandleEntityChanges.length; i++){ this._evtHandleEntityChanges[i].off(); } this._evtHandleEntityChanges.length = 0; } _onHandleElementGain() { this._handleEntityElementSubscribe(); this._destroyDragHelper(); this._handleDragHelper = new ElementDragHelper(this._handleEntity.element, this._getAxis()); this._handleDragHelper.on('drag:move', this._onHandleDrag, this); this._updateHandlePositionAndSize(); } _onHandleElementLose() { this._handleEntityElementUnsubscribe(); this._destroyDragHelper(); } _onHandleDrag(position) { if (this._handleEntity && this.enabled && this.entity.enabled) { this.value = this._handlePositionToScrollValue(position[this._getAxis()]); } } _onSetValue(name, oldValue, newValue) { if (Math.abs(newValue - oldValue) > 1e-5) { this.data.value = math.clamp(newValue, 0, 1); this._updateHandlePositionAndSize(); this.fire('set:value', this.data.value); } } _onSetHandleSize(name, oldValue, newValue) { if (Math.abs(newValue - oldValue) > 1e-5) { this.data.handleSize = math.clamp(newValue, 0, 1); this._updateHandlePositionAndSize(); } } _onSetHandleAlignment() { this._updateHandlePositionAndSize(); } _onSetOrientation(name, oldValue, newValue) { if (newValue !== oldValue && this._handleEntity?.element) { this._handleEntity.element[this._getOppositeDimension()] = 0; } } _updateHandlePositionAndSize() { const handleEntity = this._handleEntity; const handleElement = handleEntity?.element; if (handleEntity) { const position = handleEntity.getLocalPosition(); position[this._getAxis()] = this._getHandlePosition(); handleEntity.setLocalPosition(position); } if (handleElement) { handleElement[this._getDimension()] = this._getHandleLength(); } } _handlePositionToScrollValue(handlePosition) { return handlePosition * this._getSign() / this._getUsableTrackLength(); } _scrollValueToHandlePosition(value) { return value * this._getSign() * this._getUsableTrackLength(); } _getUsableTrackLength() { return Math.max(this._getTrackLength() - this._getHandleLength(), 0.001); } _getTrackLength() { if (this.entity.element) { return this.orientation === ORIENTATION_HORIZONTAL ? this.entity.element.calculatedWidth : this.entity.element.calculatedHeight; } return 0; } _getHandleLength() { return this._getTrackLength() * this.handleSize; } _getHandlePosition() { return this._scrollValueToHandlePosition(this.value); } _getSign() { return this.orientation === ORIENTATION_HORIZONTAL ? 1 : -1; } _getAxis() { return this.orientation === ORIENTATION_HORIZONTAL ? 'x' : 'y'; } _getDimension() { return this.orientation === ORIENTATION_HORIZONTAL ? 'width' : 'height'; } _getOppositeDimension() { return this.orientation === ORIENTATION_HORIZONTAL ? 'height' : 'width'; } _destroyDragHelper() { if (this._handleDragHelper) { this._handleDragHelper.destroy(); } } _setHandleDraggingEnabled(enabled) { if (this._handleDragHelper) { this._handleDragHelper.enabled = enabled; } } onEnable() { this._setHandleDraggingEnabled(true); } onDisable() { this._setHandleDraggingEnabled(false); } onRemove() { this._destroyDragHelper(); this._toggleLifecycleListeners('off'); } resolveDuplicatedEntityReferenceProperties(oldScrollbar, duplicatedIdsMap) { if (oldScrollbar.handleEntity) { this.handleEntity = duplicatedIdsMap[oldScrollbar.handleEntity.getGuid()]; } } } export { ScrollbarComponent };