slave-princess-charlotte/data/Script/base/base-scrollbar.js
2025-10-12 13:17:46 -05:00

618 lines
14 KiB
JavaScript

var ScrollbarInput = {
SELECT: 0,
CANCEL: 1,
NONE: 2,
OPTION: 3,
START: 4
};
var BaseScrollbar = defineObject(BaseObject,
{
_col: 0,
_rowCount: 0,
_showRowCount: 0,
_objectWidth: 0,
_objectHeight: 0,
_xScroll: 0,
_yScroll: 0,
_edgeCursor: null,
_commandCursor: null,
_objectArray: null,
_isActive: false,
_forceSelectIndex: -1,
_isPageChange: false,
_inputType: -1,
_prevIndex: -1,
initialize: function() {
},
moveInput: function() {
var input;
if (root.isInputAction(InputType.BTN1) || this._isScrollbarObjectPressed()) {
this.playSelectSound();
input = ScrollbarInput.SELECT;
}
else if (InputControl.isCancelAction()) {
this.playCancelSound();
input = ScrollbarInput.CANCEL;
}
else if (InputControl.isOptionAction()) {
this.playOptionSound();
input = ScrollbarInput.OPTION;
}
else if (InputControl.isStartAction()) {
this.playStartSound();
input = ScrollbarInput.START;
}
else {
this.moveScrollbarCursor();
input = ScrollbarInput.NONE;
}
return input;
},
moveScrollbarCursor: function() {
var inputType = this._commandCursor.moveCursor();
if (this._rowCount === 1) {
// 横のみ項目が並ぶ場合
this._xScroll = this._changeScrollValue(inputType, this._xScroll, true);
}
else {
// 縦にも項目が並ぶ場合
this._yScroll = this._changeScrollValue(inputType, this._yScroll, false);
}
if (this._isPageChange) {
this._checkPage(inputType);
}
this._edgeCursor.moveCursor();
MouseControl.checkScrollbarEdgeAction(this);
MouseControl.checkScrollbarWheel(this);
this.moveScrollbarContent();
if (inputType === InputType.NONE) {
inputType = MouseControl.moveScrollbarMouse(this);
}
this._inputType = inputType;
return inputType;
},
moveScrollbarContent: function() {
return true;
},
drawScrollbar: function(xStart, yStart) {
var i, j, x, y, isSelect, scrollableData;
var isLast = false;
var objectCount = this.getObjectCount();
var width = this._objectWidth + this.getSpaceX();
var height = this._objectHeight + this.getSpaceY();
var index = (this._yScroll * this._col) + this._xScroll;
xStart += this.getScrollXPadding();
yStart += this.getScrollYPadding();
// draw系でデータの更新はするべきではないが、move系での位置参照のため例外とする
this.xRendering = xStart;
this.yRendering = yStart;
MouseControl.saveRenderingPos(this);
for (i = 0; i < this._rowCount; i++) {
y = yStart + (i * height);
this.drawDescriptionLine(xStart, y);
for (j = 0; j < this._col; j++) {
x = xStart + (j * width);
isSelect = index === this.getIndex();
this.drawScrollContent(x, y, this._objectArray[index], isSelect, index);
if (isSelect && this._isActive) {
this.drawCursor(x, y, true);
}
if (index === this._forceSelectIndex) {
this.drawCursor(x, y, false);
}
if (++index === objectCount) {
isLast = true;
break;
}
}
if (isLast) {
break;
}
}
if (this._isActive) {
scrollableData = this.getScrollableData();
this._edgeCursor.drawHorzCursor(xStart - this.getScrollXPadding(), yStart - this.getScrollYPadding(), scrollableData.isLeft, scrollableData.isRight);
this._edgeCursor.drawVertCursor(xStart - this.getScrollXPadding(), yStart - this.getScrollYPadding(), scrollableData.isTop, scrollableData.isBottom);
}
},
getScrollableData: function() {
var d;
var isLeft = false;
var isTop = false;
var isRight = false;
var isBottom = false;
if (this._rowCount === 1) {
d = this._col + this._xScroll;
// 1つでもスクロールしていれば、左向きのカーソルを表示
isLeft = this._xScroll > 0;
isRight = d < this._objectArray.length;
}
else {
// 見えている範囲と、スクロールしないと見れない範囲を加算
d = (this._showRowCount * this._col) + (this._col * this._yScroll);
// 1つでもスクロールしていれば、上向きのカーソルを表示
isTop = this._yScroll > 0;
isBottom = d < this._objectArray.length;
}
return {
isLeft: isLeft,
isTop: isTop,
isRight: isRight,
isBottom: isBottom
};
},
getRecentlyInputType: function() {
return this._inputType;
},
drawCursor: function(x, y, isActive) {
var pic = this.getCursorPicture();
y = y - (32 - this._objectHeight) / 2;
this._commandCursor.drawCursor(x, y, isActive, pic);
},
drawDescriptionLine: function(x, y) {
var count;
var textui = this.getDescriptionTextUI();
var pic = textui.getUIImage();
var width = TitleRenderer.getTitlePartsWidth();
var height = TitleRenderer.getTitlePartsHeight();
if (pic !== null) {
count = Math.floor(this.getScrollbarWidth() / width) - 1;
TitleRenderer.drawTitle(pic, x - 14, y + this._objectHeight - 47, width, height, count);
}
},
drawScrollContent: function(x, y, object, isSelect, index) {
},
setScrollFormation: function(col, showRowCount) {
this._objectArray = [];
this.setScrollFormationInternal(col, showRowCount);
},
setScrollFormationInternal: function(col, showRowCount) {
this._commandCursor = createObject(CommandCursor);
this._col = col;
this._showRowCount = showRowCount;
this._objectWidth = this.getObjectWidth();
this._objectHeight = this.getObjectHeight();
this._edgeCursor = createObject(EdgeCursor);
this._edgeCursor.setEdgeRange(this.getScrollbarWidth(), this.getScrollbarHeight());
},
resetScrollData: function() {
this._objectArray = [];
this._xScroll = 0;
this._yScroll = 0;
this._rowCount = 0;
},
objectSet: function(obj) {
this._objectArray.push(obj);
},
objectSetEnd: function() {
var objectCount = this._objectArray.length;
if (this._col === 1) {
this._commandCursor.setCursorUpDown(objectCount);
}
else if (this._showRowCount === 1) {
this._commandCursor.setCursorLeftRight(objectCount);
}
else {
this._commandCursor.setCursorCross(objectCount, this._col);
}
this._rowCount = Math.ceil(objectCount / this._col);
if (this._rowCount > this._showRowCount) {
this._rowCount = this._showRowCount;
}
// 以前のインデックス数が新しいカウントを超過していないか検証
this._commandCursor.validate();
},
setObjectArray: function(objectArray) {
var i;
var length = objectArray.length;
this.resetScrollData();
for (i = 0; i < length; i++) {
this.objectSet(objectArray[i]);
}
this.objectSetEnd();
},
setDataList: function(list) {
var i, count, data;
this.resetScrollData();
count = list.getCount();
for (i = 0; i < count; i++) {
data = list.getData(i);
this.objectSet(data);
}
this.objectSetEnd();
},
cut: function(index) {
this._objectArray.splice(index, 1);
},
getIndex: function() {
return this._commandCursor.getCommandCursorIndex();
},
setIndex: function(index) {
var pos;
this._commandCursor.setCommandCursorIndex(index);
if (this._rowCount === 1) {
// 横にのみ項目が並ぶ場合
pos = index + 1;
if (pos > this._col) {
this._xScroll = pos - this._col;
}
else {
this._xScroll = 0;
}
}
else {
// 縦にも項目が並ぶ場合
pos = Math.floor(index / this._col) + 1;
if (pos > this._rowCount) {
this._yScroll = pos - this._rowCount;
}
else {
this._yScroll = 0;
}
}
},
getObject: function() {
return this.getObjectFromIndex(this.getIndex());
},
getObjectFromIndex: function(index) {
if (this._objectArray === null || this._objectArray.length === 0) {
return null;
}
return this._objectArray[index];
},
getIndexFromObject: function(object) {
var i;
var count = this._objectArray.length;
for (i = 0; i < count; i++) {
if (this._objectArray[i] === object) {
return i;
}
}
return -1;
},
getObjectCount: function() {
return this._objectArray.length;
},
getCol: function() {
return this._col;
},
getRowCount: function() {
return this._rowCount;
},
getShowRowCount: function() {
return this._showRowCount;
},
getCursorPicture: function() {
return root.queryUI('menu_selectCursor');
},
enableSelectCursor: function(isActive) {
if (isActive) {
this.setForceSelect(-1);
}
else {
this.setForceSelect(this.getIndex());
}
this.setActive(isActive);
},
setActive: function(isActive) {
if (isActive) {
MouseControl.setActiveScrollbar(this);
}
this._isActive = isActive;
},
setActiveSingle: function(isActive) {
this._isActive = isActive;
},
setForceSelect: function(index) {
this._forceSelectIndex = index;
},
getForceSelectIndex: function() {
return this._forceSelectIndex;
},
enablePageChange: function() {
this._isPageChange = true;
},
getScrollXValue: function() {
return this._xScroll;
},
getScrollYValue: function() {
return this._yScroll;
},
setScrollXValue: function(x) {
this._xScroll = x;
},
setScrollYValue: function(y) {
this._yScroll = y;
},
getScrollXPadding: function() {
return 0;
},
getScrollYPadding: function() {
return 0;
},
getSpaceX: function() {
return 0;
},
getSpaceY: function() {
return 0;
},
getObjectWidth: function() {
return 0;
},
getObjectHeight: function() {
return 0;
},
getScrollbarWidth: function() {
return (this._col * this._objectWidth) + ((this._col - 1) * this.getSpaceX());
},
getScrollbarHeight: function() {
return (this._showRowCount * this._objectHeight) + ((this._showRowCount - 1) * this.getSpaceY());
},
getParentTextUI: function() {
return this.getParentInstance().getWindowTextUI();
},
getDescriptionTextUI: function() {
return root.queryTextUI('description_title');
},
playSelectSound: function() {
MediaControl.soundDirect('commandselect');
},
playCancelSound: function() {
MediaControl.soundDirect('commandcancel');
},
playPageCursorSound: function() {
MediaControl.soundDirect('commandcursor');
},
playOptionSound: function() {
// Option時の効果音はその時々に応じて最適なものあると思われるため、ここで実装しない
},
playStartSound: function() {
// Start時の効果音はその時々に応じて最適なものあると思われるため、ここで実装しない
},
getEdgeCursor: function() {
return this._edgeCursor;
},
getCommandCursor: function() {
return this._commandCursor;
},
saveScroll: function() {
this._saveScrollY = this._yScroll;
},
restoreScroll: function() {
if ((this._saveScrollY - 1) + this._showRowCount <= this.getIndex()) {
// カーソルが見えなくなることを防ぐため、スクロール値を下げない
}
else if (this._saveScrollY > 0) {
this._saveScrollY--;
}
this._yScroll = this._saveScrollY;
},
checkAndUpdateIndex: function() {
var index = this.getIndex();
var isChanged = this._prevIndex !== index;
if (isChanged) {
this._prevIndex = index;
}
return isChanged;
},
_changeScrollValue: function(input, scrollValue, isHorz) {
var showRange, div, pos, max;
var objectCount = this._objectArray.length;
if (isHorz) {
showRange = this._col;
div = 1;
pos = this._commandCursor.getCommandCursorIndex();
}
else {
showRange = this._showRowCount;
div = this._col;
pos = Math.floor(this._commandCursor.getCommandCursorIndex() / this._col);
}
if (input === DirectionType.LEFT || input === DirectionType.TOP) {
if (pos + 1 === scrollValue) {
// 表示範囲の最上部に到達したから、スクロールする
scrollValue--;
}
else if (this._commandCursor.getCommandCursorIndex() === objectCount - 1) {
// index値が最大値になったため、スクロール値も最大値にする
max = objectCount - (showRange * div);
if (max < 0) {
scrollValue = 0;
}
else {
scrollValue = Math.ceil(max / div);
}
}
}
else if (input === DirectionType.RIGHT || input === DirectionType.BOTTOM) {
if (pos === showRange + scrollValue) {
// 表示範囲の最下部に到達したから、スクロールする
scrollValue++;
}
else if (this._commandCursor.getCommandCursorIndex() === 0) {
// index値が初期値になったため、スクロール値も初期値にする
scrollValue = 0;
}
}
return scrollValue;
},
_checkPage: function(inputType) {
var d;
var isChange = false;
var index = this.getIndex();
var yScroll = this.getScrollYValue();
var showRowCount = this.getShowRowCount();
if (inputType === InputType.LEFT) {
if (this.getObjectCount() > showRowCount) {
d = this._getPageValue(yScroll, showRowCount * -1);
yScroll -= d;
index -= d;
isChange = true;
}
}
else if (inputType === InputType.RIGHT) {
if (this.getObjectCount() > showRowCount) {
d = this._getPageValue(yScroll, showRowCount);
yScroll += d;
index += d;
isChange = true;
}
}
if (isChange) {
if (index !== this.getIndex()) {
this.setIndex(index);
this.setScrollYValue(yScroll);
this.playPageCursorSound();
}
}
},
_getPageValue: function(yScroll, n) {
var d;
var yMin = 0;
var yMax = this.getObjectCount() - this.getShowRowCount();
if (n < 0 && yScroll === yMin) {
// 最後のページに移動
return -yMax;
}
else if (n > 0 && yScroll === yMax) {
// 最初のページに移動
return -yMax;
}
d = yScroll + n;
if (yMin >= d) {
d = yScroll;
}
else if (yMax < d) {
d = yMax - yScroll;
}
else {
d = this.getShowRowCount();
}
return d;
},
_isScrollbarObjectPressed: function() {
return MouseControl.isScrollbarObjectPressed(this);
}
}
);