Source: Window_Scrollable.js

Window_Scrollable.js

//-----------------------------------------------------------------------------
// Window_Scrollable
//
// The window class with scroll functions.
/**
 * The window class with scroll functions.
 *
 * @class
 * @extends Window_Base
 */
function Window_Scrollable() {
    this.initialize(...arguments);
}

Window_Scrollable.prototype = Object.create(Window_Base.prototype);
Window_Scrollable.prototype.constructor = Window_Scrollable;

Window_Scrollable.prototype.initialize = function(rect) {
    Window_Base.prototype.initialize.call(this, rect);
    this._scrollX = 0;
    this._scrollY = 0;
    this._scrollBaseX = 0;
    this._scrollBaseY = 0;
    this.clearScrollStatus();
};

/**
 * Clears scrolling status to defaults
 */
Window_Scrollable.prototype.clearScrollStatus = function() {
    this._scrollTargetX = 0;
    this._scrollTargetY = 0;
    this._scrollDuration = 0;
    this._scrollAccelX = 0;
    this._scrollAccelY = 0;
    this._scrollTouching = false;
    this._scrollLastTouchX = 0;
    this._scrollLastTouchY = 0;
    this._scrollLastCursorVisible = false;
};

/**
 * Get the current scroll X position
 *
 * @return {number} The x position of the scroll
 */
Window_Scrollable.prototype.scrollX = function() {
    return this._scrollX;
};

/**
 * Get the current scroll Y position
 *
 * @return {number} The y position of the scroll
 */
Window_Scrollable.prototype.scrollY = function() {
    return this._scrollY;
};

/**
 * Get the base scroll X position
 *
 * @return {number} The base scroll X position
 */
Window_Scrollable.prototype.scrollBaseX = function() {
    return this._scrollBaseX;
};

/**
 * Get the base scroll Y position
 *
 * @return {number} The base scroll Y position
 */
Window_Scrollable.prototype.scrollBaseY = function() {
    return this._scrollBaseY;
};

/**
 * Scroll to a set position
 *
 * @param {number} x - The x position to scroll to
 * @param {number} y - The y position to scroll to
 */
Window_Scrollable.prototype.scrollTo = function(x, y) {
    const scrollX = x.clamp(0, this.maxScrollX());
    const scrollY = y.clamp(0, this.maxScrollY());
    if (this._scrollX !== scrollX || this._scrollY !== scrollY) {
        this._scrollX = scrollX;
        this._scrollY = scrollY;
        this.updateOrigin();
    }
};

/**
 * Add to the x and y scroll position
 *
 * @param {number} x - The amount to add to the scroll x position
 * @param {number} y - The amount to add to the scroll y position
 */
Window_Scrollable.prototype.scrollBy = function(x, y) {
    this.scrollTo(this._scrollX + x, this._scrollY + y);
};

/**
 * Scroll to a set position over an amount of time
 *
 * @param {number} x - The x position to scroll to
 * @param {number} y - The y position to scroll to
 */
Window_Scrollable.prototype.smoothScrollTo = function(x, y) {
    this._scrollTargetX = x.clamp(0, this.maxScrollX());
    this._scrollTargetY = y.clamp(0, this.maxScrollY());
    this._scrollDuration = Input.keyRepeatInterval;
};

/**
 * Add to the x and y scroll position over an amount of time
 *
 * @param {number} x - The amount to add to the scroll x position
 * @param {number} y - The amount to add to the scroll y position
 */
Window_Scrollable.prototype.smoothScrollBy = function(x, y) {
    if (this._scrollDuration === 0) {
        this._scrollTargetX = this.scrollX();
        this._scrollTargetY = this.scrollY();
    }
    this.smoothScrollTo(this._scrollTargetX + x, this._scrollTargetY + y);
};

/**
 * Sets the x and y scroll acceleration
 *
 * @param {number} x - The x scroll acceleration
 * @param {number} y - The y scroll acceleration
 */
Window_Scrollable.prototype.setScrollAccel = function(x, y) {
    this._scrollAccelX = x;
    this._scrollAccelY = y;
};

/**
 * Get the overall width of the window
 *
 * @return {number} The overall width of the window
 */
Window_Scrollable.prototype.overallWidth = function() {
    return this.innerWidth;
};

/**
 * Get the overall height of the window
 *
 * @return {number} The overall height of the window
 */
Window_Scrollable.prototype.overallHeight = function() {
    return this.innerHeight;
};

/**
 * Get the maximum scroll x position
 *
 * @return {number} The maximum scroll x position 
 */
Window_Scrollable.prototype.maxScrollX = function() {
    return Math.max(0, this.overallWidth() - this.innerWidth);
};

/**
 * Get the maximum scroll y position
 *
 * @return {number} The maximum scroll y position 
 */
Window_Scrollable.prototype.maxScrollY = function() {
    return Math.max(0, this.overallHeight() - this.innerHeight);
};

/**
 * Get the width of one block for scrolling
 *
 * @return {number} The width of a scroll block
 */
Window_Scrollable.prototype.scrollBlockWidth = function() {
    return this.itemWidth();
};

/**
 * Get the height of one block for scrolling
 *
 * @return {number} The height of a scroll block
 */
Window_Scrollable.prototype.scrollBlockHeight = function() {
    return this.itemHeight();
};

/**
 * Smoothly scroll down
 *
 * @param {number} n - The amount of items to scroll down
 */
Window_Scrollable.prototype.smoothScrollDown = function(n) {
    this.smoothScrollBy(0, this.itemHeight() * n);
};

/**
 * Smoothly scroll up
 *
 * @param {number} n - The amount of items to scroll up
 */
Window_Scrollable.prototype.smoothScrollUp = function(n) {
    this.smoothScrollBy(0, -this.itemHeight() * n);
};

Window_Scrollable.prototype.update = function() {
    Window_Base.prototype.update.call(this);
    this.processWheelScroll();
    this.processTouchScroll();
    this.updateSmoothScroll();
    this.updateScrollAccel();
    this.updateArrows();
    this.updateOrigin();
};

/**
 * Processing for scrolling by mouse wheel
 */
Window_Scrollable.prototype.processWheelScroll = function() {
    if (this.isWheelScrollEnabled() && this.isTouchedInsideFrame()) {
        const threshold = 20;
        if (TouchInput.wheelY >= threshold) {
            this.smoothScrollDown(1);
        }
        if (TouchInput.wheelY <= -threshold) {
            this.smoothScrollUp(1);
        }
    }
};

/**
 * Processing for scrolling by touch
 */
Window_Scrollable.prototype.processTouchScroll = function() {
    if (this.isTouchScrollEnabled()) {
        if (TouchInput.isTriggered() && this.isTouchedInsideFrame()) {
            this.onTouchScrollStart();
        }
        if (this._scrollTouching) {
            if (TouchInput.isReleased()) {
                this.onTouchScrollEnd();
            } else if (TouchInput.isMoved()) {
                this.onTouchScroll();
            }
        }
    }
};

/**
 * Check if wheel scrolling is enabled
 *
 * @return {boolean} True if the player can scroll the window using the mouse wheel
 */
Window_Scrollable.prototype.isWheelScrollEnabled = function() {
    return this.isScrollEnabled();
};

/**
 * Check if touch scrolling is enabled
 *
 * @return {boolean} True if the player can scroll the window using the touch controls
 */
Window_Scrollable.prototype.isTouchScrollEnabled = function() {
    return this.isScrollEnabled();
};

/**
 * Check if scrolling is enabled
 *
 * @return {boolean} True if the player can scroll the window
 */
Window_Scrollable.prototype.isScrollEnabled = function() {
    return true;
};

/**
 * Check if the last touch input was inside the window
 *
 * @return {boolean} True if touched inside the window
 */
Window_Scrollable.prototype.isTouchedInsideFrame = function() {
    const touchPos = new Point(TouchInput.x, TouchInput.y);
    const localPos = this.worldTransform.applyInverse(touchPos);
    return this.innerRect.contains(localPos.x, localPos.y);
};

/**
 * Handling for when scrolling starts
 */
Window_Scrollable.prototype.onTouchScrollStart = function() {
    this._scrollTouching = true;
    this._scrollLastTouchX = TouchInput.x;
    this._scrollLastTouchY = TouchInput.y;
    this._scrollLastCursorVisible = this.cursorVisible;
    this.setScrollAccel(0, 0);
};

/**
 * Handling for when touch scrolling starts
 */
Window_Scrollable.prototype.onTouchScroll = function() {
    const accelX = this._scrollLastTouchX - TouchInput.x;
    const accelY = this._scrollLastTouchY - TouchInput.y;
    this.setScrollAccel(accelX, accelY);
    this._scrollLastTouchX = TouchInput.x;
    this._scrollLastTouchY = TouchInput.y;
    this.cursorVisible = false;
};

/**
 * Handling for when touch scrolling ends
 */
Window_Scrollable.prototype.onTouchScrollEnd = function() {
    this._scrollTouching = false;
    this.cursorVisible = this._scrollLastCursorVisible;
};

/**
 * Updates smooth scrolling
 */
Window_Scrollable.prototype.updateSmoothScroll = function() {
    if (this._scrollDuration > 0) {
        const d = this._scrollDuration;
        const deltaX = (this._scrollTargetX - this._scrollX) / d;
        const deltaY = (this._scrollTargetY - this._scrollY) / d;
        this.scrollBy(deltaX, deltaY);
        this._scrollDuration--;
    }
};

/**
 * Updates the scroll acceleration
 */
Window_Scrollable.prototype.updateScrollAccel = function() {
    if (this._scrollAccelX !== 0 || this._scrollAccelY !== 0) {
        this.scrollBy(this._scrollAccelX, this._scrollAccelY);
        this._scrollAccelX *= 0.92;
        this._scrollAccelY *= 0.92;
        if (Math.abs(this._scrollAccelX) < 1) {
            this._scrollAccelX = 0;
        }
        if (Math.abs(this._scrollAccelY) < 1) {
            this._scrollAccelY = 0;
        }
    }
};

/**
 * Updates the arrow up/down visibility
 */
Window_Scrollable.prototype.updateArrows = function() {
    this.downArrowVisible = this._scrollY < this.maxScrollY();
    this.upArrowVisible = this._scrollY > 0;
};

/**
 * Updates the window origin
 */
Window_Scrollable.prototype.updateOrigin = function() {
    const blockWidth = this.scrollBlockWidth() || 1;
    const blockHeight = this.scrollBlockHeight() || 1;
    const baseX = this._scrollX - (this._scrollX % blockWidth);
    const baseY = this._scrollY - (this._scrollY % blockHeight);
    if (baseX !== this._scrollBaseX || baseY !== this._scrollBaseY) {
        this.updateScrollBase(baseX, baseY);
        this.paint();
    }
    this.origin.x = this._scrollX % blockWidth;
    this.origin.y = this._scrollY % blockHeight;
};

/**
 * Updates the scroll base
 *
 * @param {number} baseX - The new base x of the scroll
 * @param {number} baseY - The new base y of the scroll
 */
Window_Scrollable.prototype.updateScrollBase = function(baseX, baseY) {
    const deltaX = baseX - this._scrollBaseX;
    const deltaY = baseY - this._scrollBaseY;
    this._scrollBaseX = baseX;
    this._scrollBaseY = baseY;
    this.moveCursorBy(-deltaX, -deltaY);
    this.moveInnerChildrenBy(-deltaX, -deltaY);
};

/**
 * Paints window contents. Meant to be overridden - does nothing by default.
 */
Window_Scrollable.prototype.paint = function() {
    // to be overridden
};