362 lines
11 KiB
JavaScript
362 lines
11 KiB
JavaScript
//=============================================================================
|
|
// RPG Maker MZ - Sprite_InputHandle
|
|
//
|
|
// Copyright 2024 Panzer-IV. All rights reserved.
|
|
// This source code or any portion thereof must not be
|
|
// reproduced or used without licensed in any manner whatsoever.
|
|
//=============================================================================
|
|
/*:
|
|
* @target MZ
|
|
* @plugindesc 入力対応スプライト
|
|
* @author 四号戦車
|
|
* @base DebugSwitch
|
|
* @base AsyncLoadImage
|
|
* @base SmartAnimation
|
|
* @orderAfter DebugSwitch
|
|
* @orderAfter AsyncLoadImage
|
|
* @orderAfter SmartAnimation
|
|
*
|
|
* @param comment
|
|
* @text 備考欄
|
|
* @desc プラグイン側では使用しません。
|
|
* メモ欄としてお使いください。
|
|
* @type multiline_string
|
|
* @default
|
|
*
|
|
* @help Sprite_InputHandle.js
|
|
*
|
|
* Version: 0.0.1
|
|
*
|
|
* 内部のDisplayObjectの展開領域に関わらず固定の表示領域にクロップするSpriteです。
|
|
*/
|
|
(() => {
|
|
"use strict";
|
|
|
|
//========================================================================
|
|
// プラグイン定義
|
|
//========================================================================
|
|
const pluginName = "Sprite_InputHandle";
|
|
const script = document.currentScript;
|
|
const param = PluginManagerEx.createParameter(script);
|
|
|
|
//========================================================================
|
|
// 定数定義
|
|
//========================================================================
|
|
|
|
//========================================================================
|
|
// クラス定義 (Sprite_InputHandle)
|
|
//========================================================================
|
|
class Sprite_InputHandle extends Sprite {
|
|
constructor(bitmap) {
|
|
super(bitmap);
|
|
this._enterListeners = [];
|
|
this._hoverListeners = [];
|
|
|
|
this._pressed = false;
|
|
this._hovered = false;
|
|
this._isTouchEnabled = true;
|
|
this._isKeepEntryUntilDragging = false;
|
|
this._excludeTransparentPixel = false;
|
|
this._lastSnappedChildren = 0;
|
|
this._snap = null;
|
|
}
|
|
|
|
onHandleEnter() {
|
|
if (this.isTouchEnabled()) {
|
|
this._fireEnter(this._name);
|
|
}
|
|
}
|
|
|
|
onPressed(pressed) {
|
|
}
|
|
|
|
onPointerEntry(entry) {
|
|
if (this.isTouchEnabled()) {
|
|
this._fireHover(this._name, entry);
|
|
}
|
|
}
|
|
|
|
addEnterListener(listener) {
|
|
if (!!listener && typeof listener === 'function') {
|
|
this._enterListeners.push(listener);
|
|
}
|
|
}
|
|
|
|
removeEnterListener(listener) {
|
|
this._enterListeners = this._enterListeners.filter(l => l !== listener);
|
|
}
|
|
|
|
addHoverListener(listener) {
|
|
if (!!listener && typeof listener === 'function') {
|
|
this._hoverListeners.push(listener);
|
|
}
|
|
}
|
|
|
|
removeHoverListener(listener) {
|
|
this._hoverListeners = this._hoverListeners.filter(l => l !== listener);
|
|
}
|
|
|
|
update() {
|
|
super.update();
|
|
this.updateSnap();
|
|
this.processTouch();
|
|
}
|
|
|
|
isTouchEnabled() {
|
|
return this.worldVisible && this.isTouchEnable();
|
|
}
|
|
|
|
enableTouch(value) {
|
|
this._isTouchEnabled = value;
|
|
}
|
|
|
|
isTouchEnable() {
|
|
return this._isTouchEnabled;
|
|
}
|
|
|
|
isKeepEntryUntilDragging() {
|
|
return this._isKeepEntryUntilDragging;
|
|
}
|
|
|
|
isPressed() {
|
|
return this._pressed;
|
|
}
|
|
|
|
isHovered() {
|
|
return this._hovered;
|
|
}
|
|
|
|
isBeingTouched() {
|
|
const touchPos = new Point(TouchInput.x, TouchInput.y);
|
|
const localPos = this.worldTransform.applyInverse(touchPos);
|
|
return this.hitTest(localPos.x, localPos.y);
|
|
}
|
|
|
|
createSnap() {
|
|
const width = this.width;
|
|
const height = this.height;
|
|
const bitmap = new Bitmap(width, height);
|
|
const renderTexture = PIXI.RenderTexture.create(width, height);
|
|
|
|
const renderer = Graphics.app.renderer;
|
|
renderer.render(this, renderTexture);
|
|
this.worldTransform.identity();
|
|
const canvas = renderer.extract.canvas(renderTexture);
|
|
bitmap.context.drawImage(canvas, 0, 0);
|
|
canvas.width = 0;
|
|
canvas.height = 0;
|
|
|
|
renderTexture.destroy({ destroyBase: true });
|
|
bitmap.baseTexture.update();
|
|
|
|
this._lastSnappedChildren = this.children.length;
|
|
|
|
return bitmap;
|
|
}
|
|
|
|
getSnap() {
|
|
if (!this._snap || (this.children.length !== this._lastSnappedChildren)) {
|
|
this._snap = this.createSnap();
|
|
}
|
|
return this._snap;
|
|
}
|
|
|
|
updateSnap() {
|
|
if (this._excludeTransparentPixel) {
|
|
const childrenSize = this.children.length;
|
|
if (childrenSize !== this._lastSnappedChildren) {
|
|
this._snap = this.createSnap();
|
|
}
|
|
}
|
|
}
|
|
|
|
hitTest(x, y) {
|
|
const rect = new Rectangle(
|
|
-this.anchor.x * this.width,
|
|
-this.anchor.y * this.height,
|
|
this.width,
|
|
this.height
|
|
);
|
|
|
|
if (this._excludeTransparentPixel === true) {
|
|
if (rect.contains(x, y)) {
|
|
const snap = this.getSnap();
|
|
const alpha = snap.getAlphaPixel(x, y);
|
|
snap.destroy();
|
|
return alpha > 0;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return rect.contains(x, y);
|
|
}
|
|
}
|
|
|
|
isIncludeOnParentFrame() {
|
|
if (this.worldVisible === false) {
|
|
return false;
|
|
}
|
|
|
|
let item = this.parent;
|
|
while (!!item) {
|
|
if (item instanceof Sprite_Scrollable) {
|
|
if (!item.isTouchedInsideFrame()) {
|
|
return false;
|
|
}
|
|
}
|
|
item = item.parent;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
processTouch() {
|
|
if (this.isTouchEnabled()) {
|
|
if (this.isBeingTouched() || (this.isKeepEntryUntilDragging() && this.isPressed())) {
|
|
if (!this._hovered && TouchInput.isHovered()) {
|
|
this._hovered = true;
|
|
this.onPointerEntry(true);
|
|
}
|
|
if (TouchInput.isTriggered()) {
|
|
this.onPressed(true);
|
|
this._pressed = true;
|
|
}
|
|
} else {
|
|
if (this._hovered) {
|
|
this.onPointerEntry(false);
|
|
}
|
|
this._pressed = false;
|
|
this._hovered = false;
|
|
}
|
|
if (this._pressed && TouchInput.isReleased() && this.isIncludeOnParentFrame()) {
|
|
this.onHandleEnter();
|
|
this.onPressed(false);
|
|
this._pressed = false;
|
|
}
|
|
} else {
|
|
if (this._pressed) {
|
|
this.onPressed(false);
|
|
this._pressed = false;
|
|
}
|
|
|
|
if (this._hovered) {
|
|
this.onPointerEntry(false);
|
|
this._hovered = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
_checkTouchInput() {
|
|
const point = this.toLocal(new Point(TouchInput.x, TouchInput.y));
|
|
const bounds = this.getLocalBounds();
|
|
return bounds.contains(point.x, point.y);
|
|
}
|
|
|
|
_fireEnter() {
|
|
this._enterListeners.forEach(listener => {
|
|
listener(this);
|
|
})
|
|
}
|
|
|
|
_fireHover(inEntry) {
|
|
this._hoverListeners.forEach(listener => {
|
|
listener(this, inEntry);
|
|
})
|
|
}
|
|
|
|
enableTransparent(value) {
|
|
this._excludeTransparentPixel = !value;
|
|
}
|
|
|
|
canTouchTransparent() {
|
|
return !this._excludeTransparentPixel;
|
|
}
|
|
};
|
|
window.Sprite_InputHandle = Sprite_InputHandle;
|
|
|
|
//========================================================================
|
|
// クラス定義 (Sprite_SimpleButton)
|
|
//========================================================================
|
|
class Sprite_SimpleButton extends Sprite_InputHandle {
|
|
constructor(baseBitmap, option) {
|
|
super();
|
|
this.option = option;
|
|
this.setFrame(0, 0, baseBitmap.width, baseBitmap.height);
|
|
this.base = new Sprite(baseBitmap);
|
|
this.addChild(this.base);
|
|
|
|
const normalColor = this.getNormalColor();
|
|
if (!!normalColor) {
|
|
this.base.tint = normalColor;
|
|
}
|
|
|
|
this.content = new Sprite(new Bitmap(baseBitmap.width, baseBitmap.height));
|
|
this.content.zIndex = 1;
|
|
this.paintContent(this.content.bitmap);
|
|
this.addChild(this.content);
|
|
|
|
this._pressedMask = this.createPressedMask(baseBitmap);
|
|
this._pressedMask.zIndex = 2;
|
|
this.addChild(this._pressedMask);
|
|
this._pressedMask.hide();
|
|
|
|
this.focused = false;
|
|
this.interactive = true;
|
|
this.buttonMode = true;
|
|
}
|
|
|
|
paintContent(content) {
|
|
// for sub-class override
|
|
}
|
|
|
|
getNormalColor() {
|
|
// for sub-class override
|
|
return undefined;
|
|
}
|
|
|
|
getFocusColor() {
|
|
// for sub-class override
|
|
return undefined;
|
|
}
|
|
|
|
createPressedMask(baseBitmap) {
|
|
const bitmap = new Bitmap(baseBitmap.width, baseBitmap.height);
|
|
const sprite = new Sprite(bitmap);
|
|
|
|
const mask = new Sprite(baseBitmap);
|
|
sprite.addChild(mask);
|
|
sprite.mask = mask;
|
|
|
|
bitmap.paintOpacity = PluginUtils.percent(255, 40);
|
|
bitmap.fillAll('#000000');
|
|
bitmap.paintOpacity = 255;
|
|
|
|
return sprite;
|
|
}
|
|
|
|
setFocus(focus) {
|
|
if (this.focused !== focus) {
|
|
const tint = focus ? this.getFocusColor() : this.getNormalColor();
|
|
if (!!tint) {
|
|
this.base.tint = tint;
|
|
}
|
|
}
|
|
this.focused = focus;
|
|
}
|
|
|
|
isFocused() {
|
|
return this.focused;
|
|
}
|
|
|
|
onPointerEntry(entry) {
|
|
super.onPointerEntry(entry);
|
|
this.setFocus(entry);
|
|
}
|
|
|
|
onPressed(pressed) {
|
|
super.onPressed(pressed);
|
|
Logger.d(`onPressed: pressed = ${pressed}`);
|
|
this._pressedMask.visible = pressed;
|
|
}
|
|
}
|
|
window.Sprite_SimpleButton = Sprite_SimpleButton;
|
|
})();
|