Skip to content

Commit

Permalink
#154 TextFieldのhit testを実装(WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
ienaga committed Nov 17, 2024
1 parent bf3ee4a commit f147b4e
Show file tree
Hide file tree
Showing 16 changed files with 572 additions and 346 deletions.
9 changes: 7 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@
sprite.x = 50;
sprite.y = 50;

// const textFiled = sprite.addChild(new TextField());
// textFiled.text = "Hello Next2D";
const textFiled = sprite.addChild(new TextField());
textFiled.x = 150;
textFiled.y = 100;
textFiled.border = true;
textFiled.type = "input";
textFiled.multiline = true;
textFiled.text = "Hello Next2D\nTest Mode On\n\nText Field";

const shape = sprite.addChild(new Shape());
shape
Expand Down
11 changes: 10 additions & 1 deletion packages/core/src/CoreUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,21 @@ export const $getMainElement = (): HTMLDivElement =>
return $mainElement as NonNullable<HTMLDivElement>;
};

/**
* @description マウス、タップ時の画面のmatrix情報
* Screen matrix information when mouse or tap is pressed
*
* @type {Float32Array}
* @protected
*/
export const $hitMatrix: Float32Array = new Float32Array([1, 0, 0, 1, 0, 0]);

/**
* @description マウス、タップがヒットしたDisplayObjectを取得します。
* Get the DisplayObject that the mouse or tap hit.
*
* @type {IPlayerHitObject}
* @private
* @protected
*/
export const $hitObject: IPlayerHitObject = {
"x": 0,
Expand Down
29 changes: 29 additions & 0 deletions packages/core/src/Player/service/PlayerDoubleClickEventService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { DisplayObject } from "@next2d/display";
import { $stage } from "@next2d/display";
import { PointerEvent } from "@next2d/events";

/**
* @description ポインターのダブルタップイベントを処理します。
* Processes the pointer double tap event.
*
* @param {D | null} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject> (display_object: D | null = null): void =>
{
if (display_object) {
if (display_object.willTrigger(PointerEvent.DOUBLE_CLICK)) {
display_object.dispatchEvent(
new PointerEvent(PointerEvent.DOUBLE_CLICK)
);
}
} else {
if ($stage.willTrigger(PointerEvent.DOUBLE_CLICK)) {
$stage.dispatchEvent(
new PointerEvent(PointerEvent.DOUBLE_CLICK)
);
}
}
};
80 changes: 80 additions & 0 deletions packages/core/src/Player/service/PlayerPointerDownEventService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { DisplayObject } from "@next2d/display";
import type { TextField } from "@next2d/text";
import { $stage } from "@next2d/display";
import { PointerEvent } from "@next2d/events";
import {
$setSelectedTextField,
$getSelectedTextField,
$textArea
} from "@next2d/text";
import {
$hitObject,
$hitMatrix
} from "../../CoreUtil";

/**
* @description ポインターダウンイベントを処理します。
* Processes the pointer down event.
*
* @param {D | null} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject> (
display_object: D | null = null,
page_x: number = 0,
page_y: number = 0
): void => {

if (display_object) {

if (display_object.isText) {

// 選択中のTextFieldがある場合はフォーカスを解除します。
const selectedTextField = $getSelectedTextField();
if (selectedTextField
&& selectedTextField.instanceId !== display_object.instanceId
) {
selectedTextField.focus = false;
}

if (!(display_object as unknown as TextField).focus) {
(display_object as unknown as TextField).focus = true;
$setSelectedTextField(display_object as unknown as TextField);
}

(display_object as unknown as TextField).setFocusIndex(
$hitObject.x - $hitMatrix[4],
$hitObject.y - $hitMatrix[5]
);

$textArea.style.top = `${page_x}px`;
$textArea.style.left = `${page_y}px`;

} else {
// ヒットしたDisplayObjectポインターダウンイベントを発火します。
if (display_object.willTrigger(PointerEvent.POINTER_DOWN)) {
display_object.dispatchEvent(
new PointerEvent(PointerEvent.POINTER_DOWN)
);
}
}

} else {

// 選択中のTextFieldがある場合はフォーカスを解除します。
const selectedTextField = $getSelectedTextField();
if (selectedTextField) {
selectedTextField.focus = false;
$setSelectedTextField(null);
}

// ステージ全体のポインターダウンイベントを発火します。
if ($stage.willTrigger(PointerEvent.POINTER_DOWN)) {
$stage.dispatchEvent(
new PointerEvent(PointerEvent.POINTER_DOWN)
);
}
}
};
34 changes: 34 additions & 0 deletions packages/core/src/Player/service/PlayerPointerMoveEventService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { DisplayObject } from "@next2d/display";
import type { TextField } from "@next2d/text";
import { $player } from "../../Player";
import {
$hitObject,
$hitMatrix
} from "../../CoreUtil";

/**
* @description ポインタームーブイベントを処理します。
* Processes the pointer move event.
*
* @param {D | null} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject> (
display_object: D | null = null,
page_x: number = 0,
page_y: number = 0
): void => {

console.log(page_x, page_y);
if (display_object) {
if (display_object.isText && $player.mouseState === "down") {
(display_object as unknown as TextField).setFocusIndex(
$hitObject.x - $hitMatrix[4],
$hitObject.y - $hitMatrix[5],
true
);
}
}
};
29 changes: 29 additions & 0 deletions packages/core/src/Player/service/PlayerPointerUpEventService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { DisplayObject } from "@next2d/display";
import { $stage } from "@next2d/display";
import { PointerEvent } from "@next2d/events";

/**
* @description ポインターアップイベントを処理します。
* Processes the pointer up event.
*
* @param {DisplayObject | null} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject> (display_object: D | null = null): void =>
{
if (display_object) {
if (display_object.willTrigger(PointerEvent.POINTER_UP)) {
display_object.dispatchEvent(
new PointerEvent(PointerEvent.POINTER_UP)
);
}
} else {
if ($stage.willTrigger(PointerEvent.POINTER_UP)) {
$stage.dispatchEvent(
new PointerEvent(PointerEvent.POINTER_UP)
);
}
}
};
50 changes: 27 additions & 23 deletions packages/core/src/Player/usecase/PlayerHitTestUseCase.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import type { DisplayObject } from "@next2d/display";
import { $player } from "../../Player";
import { $stage } from "@next2d/display";
import { PointerEvent as Next2D_PointerEvent } from "@next2d/events";
import { execute as playerPointerDownEventService } from "../service/PlayerPointerDownEventService";
import { execute as playerDoubleClickEventService } from "../service/PlayerDoubleClickEventService";
import { execute as playerPointerUpEventService } from "../service/PlayerPointerUpEventService";
import { execute as playerPointerMoveEventService } from "../service/PlayerPointerMoveEventService";
import {
$devicePixelRatio,
$hitContext,
$getMainElement,
$hitObject
$hitObject,
$hitMatrix
} from "../../CoreUtil";

/**
* @type {Float32Array}
* @private
*/
const $matrix: Float32Array = new Float32Array([1, 0, 0, 1, 0, 0]);

/**
* @type {string}
* @private
Expand Down Expand Up @@ -68,15 +68,15 @@ export const execute = (event: PointerEvent, canvas: HTMLCanvasElement): void =>
$hitObject.hit = null;

// hit test
$matrix[4] = ($player.rendererWidth - $stage.stageWidth * $player.rendererScale) / 2;
$matrix[5] = ($player.rendererHeight - $stage.stageHeight * $player.rendererScale) / 2;
$hitMatrix[4] = ($player.rendererWidth - $stage.stageWidth * $player.rendererScale) / 2;
$hitMatrix[5] = ($player.rendererHeight - $stage.stageHeight * $player.rendererScale) / 2;

// reset
$hitContext.beginPath();
$hitContext.setTransform(1, 0, 0, 1, 0, 0);

// ヒット判定
$stage.$mouseHit($hitContext, $matrix, $hitObject);
$stage.$mouseHit($hitContext, $hitMatrix, $hitObject);

// ヒットしたオブジェクトがある場合
if ($hitObject.hit) {
Expand All @@ -88,21 +88,19 @@ export const execute = (event: PointerEvent, canvas: HTMLCanvasElement): void =>
canvas.style.cursor = $currentCursor = $hitObject.pointer;
}

switch (true) {

// ヒットしたオブジェクトがある場合
case $hitObject.hit === null:
break;
const hitDisplayObject = $hitObject.hit as DisplayObject | null;
switch (event.type) {

// ヒットしたオブジェクトがない場合
default:
case Next2D_PointerEvent.POINTER_MOVE:
playerPointerMoveEventService(
hitDisplayObject, event.pageX, event.pageY
);
break;
}

switch (event.type) {

case Next2D_PointerEvent.POINTER_DOWN:

clearTimeout($timerId);

if (!$wait) {

// 初回のタップであればダブルタップを待機モードに変更
Expand All @@ -114,18 +112,24 @@ export const execute = (event: PointerEvent, canvas: HTMLCanvasElement): void =>
$wait = false;
}, 300);

playerPointerDownEventService(
hitDisplayObject,
event.pageX,
event.pageY
);

} else {

// ダブルタップを終了
$wait = false;

playerDoubleClickEventService(hitDisplayObject);

}
break;

case Next2D_PointerEvent.POINTER_UP:
break;

case Next2D_PointerEvent.POINTER_MOVE:
playerPointerUpEventService(hitDisplayObject);
break;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const execute = (
point_y: number
): void => {

if (!text_field.visible || !text_field.text) {
if (!text_field.visible) {
render_queue.push(0);
return ;
}
Expand Down Expand Up @@ -253,6 +253,7 @@ export const execute = (
render_queue.push(Math.abs(text_field.xMax - text_field.xMin));
render_queue.push(Math.abs(text_field.yMax - text_field.yMin));
render_queue.push(text_field.focusIndex);
render_queue.push(text_field.selectIndex);
render_queue.push(+text_field.focusVisible);
render_queue.push(text_field.thickness);
render_queue.push(text_field.thicknessColor);
Expand Down
Loading

0 comments on commit f147b4e

Please sign in to comment.