feat: ���� 3D-�������-��������� � ����� + dev JWT-������ #9
@ -2212,13 +2212,23 @@ export class PlayerController {
|
||||
_setupInput() {
|
||||
const canvas = this.canvas;
|
||||
|
||||
// Задача 02: ЛКМ-клик НЕ берёт pointer-lock в third (курсор свободен для
|
||||
// GUI/3D-табличек). Lock берётся только в perma-режимах (first/lock) —
|
||||
// но там он уже взят в start(). В third lock включает только зажатая ПКМ.
|
||||
// Задача 02 (как в студии): хелпер — режим с ПОСТОЯННЫМ pointer-lock.
|
||||
const needPermLock = () => (
|
||||
this._cameraMode === 'first' ||
|
||||
this._cameraMode === 'lockfirst' ||
|
||||
this._cameraMode === 'sideview' ||
|
||||
this._shiftLock
|
||||
);
|
||||
|
||||
const onCanvasClick = () => {
|
||||
// В UI-режиме клик не перехватывает мышь.
|
||||
if (this._uiCursorMode) return;
|
||||
if (this._active && this._isPermaLockMode()
|
||||
&& document.pointerLockElement !== canvas) {
|
||||
if (!this._active) return;
|
||||
// Roblox-style: в third-person ЛКМ-клик НЕ лочит курсор (он остаётся
|
||||
// свободным для GUI/3D-onClick). Lock запрашиваем ТОЛЬКО для режимов
|
||||
// где курсор постоянно скрыт, и только если lock был снят.
|
||||
if (!needPermLock()) return;
|
||||
if (document.pointerLockElement !== canvas) {
|
||||
try {
|
||||
const p = canvas.requestPointerLock?.();
|
||||
if (p && typeof p.catch === 'function') p.catch(() => {});
|
||||
@ -2227,31 +2237,33 @@ export class PlayerController {
|
||||
};
|
||||
canvas.addEventListener('click', onCanvasClick);
|
||||
|
||||
// Задача 02: ПКМ-orbit — зажал ПКМ в third → lock + камера крутится,
|
||||
// отпустил → курсор вернулся. В perma-режимах ПКМ не нужен.
|
||||
const onRmbDown = (e) => {
|
||||
if (e.button !== 2 || this._uiCursorMode) return;
|
||||
if (!this._isPermaLockMode() && document.pointerLockElement !== canvas) {
|
||||
this._rmbHeld = true;
|
||||
// === ПКМ: в third-person удержание ПКМ запускает orbit-камеру ===
|
||||
// Зажал ПКМ → курсор скрыт, мышь крутит камеру. Отпустил → курсор вернулся.
|
||||
const onCanvasMouseDownGlobal = (e) => {
|
||||
if (!this._active || this._uiCursorMode) return;
|
||||
if (e.button !== 2) return; // только ПКМ
|
||||
if (needPermLock()) return; // в perma-режимах ПКМ ничего не делает
|
||||
this._rmbHeld = true;
|
||||
if (document.pointerLockElement !== canvas) {
|
||||
try {
|
||||
const p = canvas.requestPointerLock?.();
|
||||
if (p && typeof p.catch === 'function') p.catch(() => {});
|
||||
} catch (err) { /* ignore */ }
|
||||
}
|
||||
e.preventDefault();
|
||||
};
|
||||
const onRmbUp = (e) => {
|
||||
const onWindowMouseUpGlobal = (e) => {
|
||||
if (e.button !== 2) return;
|
||||
if (this._rmbHeld) {
|
||||
this._rmbHeld = false;
|
||||
if (!this._isPermaLockMode() && document.pointerLockElement === canvas) {
|
||||
try { document.exitPointerLock(); } catch (err) { /* ignore */ }
|
||||
}
|
||||
if (!this._rmbHeld) return;
|
||||
this._rmbHeld = false;
|
||||
if (needPermLock()) return;
|
||||
if (document.pointerLockElement === canvas) {
|
||||
try { document.exitPointerLock(); } catch (err) { /* ignore */ }
|
||||
}
|
||||
};
|
||||
const onCtxMenu = (e) => { if (!this._uiCursorMode) e.preventDefault(); };
|
||||
canvas.addEventListener('mousedown', onRmbDown);
|
||||
document.addEventListener('mouseup', onRmbUp);
|
||||
canvas.addEventListener('contextmenu', onCtxMenu);
|
||||
canvas.addEventListener('mousedown', onCanvasMouseDownGlobal);
|
||||
window.addEventListener('mouseup', onWindowMouseUpGlobal);
|
||||
canvas.addEventListener('contextmenu', (e) => { if (this._active) e.preventDefault(); });
|
||||
|
||||
// === UI-режим: mousedown / mouseup → callback (для drag-игр) ===
|
||||
const onCanvasMouseDown = (e) => {
|
||||
@ -2343,18 +2355,26 @@ export class PlayerController {
|
||||
let wasLocked = false;
|
||||
const onPointerLockChange = () => {
|
||||
const locked = document.pointerLockElement === canvas;
|
||||
this._applyCursorVisibility(); // задача 02: вернуть/скрыть курсор
|
||||
this._applyCursorVisibility?.(); // задача 02: вернуть/скрыть курсор
|
||||
if (locked) {
|
||||
wasLocked = true;
|
||||
this._rmbHeld = true; // если попали в lock — ПКМ удерживается
|
||||
} else if (wasLocked && this._active) {
|
||||
// pointer-lock снят. Причин три:
|
||||
// 1) пользователь в UI-режиме (game.input.setCursorMode('ui'))
|
||||
// 2) ПКМ отпущена в third-person (orbit-камера завершена)
|
||||
// 3) Esc → выход из Play (если был в first/lockfirst/sideview/shift)
|
||||
wasLocked = false;
|
||||
if (this._uiCursorMode) return;
|
||||
// Задача 02: в third потеря lock = отпустили ПКМ (orbit) ИЛИ
|
||||
// вышли зумом из first — это НЕ выход из Play. Выход (Esc) только
|
||||
// из perma-режимов с постоянным lock (first/lockfirst/shift-lock).
|
||||
if (this._rmbHeld) { this._rmbHeld = false; return; }
|
||||
if (this._cameraMode === 'third' || this._cameraMode === 'front') return;
|
||||
if (this._onExitRequest) this._onExitRequest();
|
||||
this._rmbHeld = false;
|
||||
if (this._uiCursorMode) { this._applyCursorVisibility?.(); return; }
|
||||
if (needPermLock()) {
|
||||
// Был режим с постоянным lock'ом и его сняли (Esc) → выход.
|
||||
if (this._onExitRequest) this._onExitRequest();
|
||||
} else {
|
||||
// Third-person: просто отпустили ПКМ. Остаёмся в Play,
|
||||
// курсор вернулся — это НЕ повод открывать меню.
|
||||
this._applyCursorVisibility?.();
|
||||
}
|
||||
}
|
||||
};
|
||||
document.addEventListener('pointerlockchange', onPointerLockChange);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user