@@ -6,7 +6,7 @@ import { FullScreenPerform } from './FullScreenPerform/FullScreenPerform';
66import { nextSentence } from '@/Core/controller/gamePlay/nextSentence' ;
77import { stopAll } from '@/Core/controller/gamePlay/fastSkip' ;
88import { useDispatch , useSelector } from 'react-redux' ;
9- import { RootState } from '@/store/store' ;
9+ import { RootState , webgalStore } from '@/store/store' ;
1010import { setVisibility } from '@/store/GUIReducer' ;
1111import { TextBoxFilm } from '@/Stage/TextBox/TextBoxFilm' ;
1212import { useHotkey } from '@/hooks/useHotkey' ;
@@ -18,52 +18,12 @@ import { IGuiState } from '@/store/guiInterface';
1818import { IStageState } from '@/store/stageInterface' ;
1919// import OldStage from '@/Components/Stage/OldStage/OldStage';
2020
21- function inTextBox ( event : React . MouseEvent ) {
22- const tb = document . getElementById ( 'textBoxMain' ) ;
23- if ( ! tb ) {
24- return false ;
25- }
26- let bounds = tb . getBoundingClientRect ( ) ;
27- return (
28- event . clientX > bounds . left &&
29- event . clientX < bounds . right &&
30- event . clientY > bounds . top &&
31- event . clientY < bounds . bottom
32- ) ;
33- }
34-
35- function checkMousePosition ( event : React . MouseEvent , GUIState : IGuiState , dispatch : ReturnType < typeof useDispatch > ) {
36- if ( ! GUIState . controlsVisibility && inTextBox ( event ) ) {
37- dispatch ( setVisibility ( { component : 'controlsVisibility' , visibility : true } ) ) ;
38- }
39- if ( GUIState . controlsVisibility && ! inTextBox ( event ) ) {
40- dispatch ( setVisibility ( { component : 'controlsVisibility' , visibility : false } ) ) ;
41- }
42- }
43-
44- function isTextboxHidden ( stageState : IStageState , GUIState : IGuiState ) {
45- if ( ! GUIState . showTextBox ) {
46- return true ;
47- }
48-
49- if ( stageState . isDisableTextbox ) {
50- return true ;
51- }
52-
53- const isText = stageState . showText !== '' || stageState . showName !== '' ;
54- if ( ! isText ) {
55- return true ;
56- }
57-
58- const isInIntro = document . getElementById ( 'introContainer' ) ?. style . display === 'block' ;
59- if ( isInIntro ) {
60- return true ;
61- }
62-
63- return false ;
64- }
65-
6621let timeoutEventHandle : ReturnType < typeof setTimeout > | null = null ;
22+ // 视为“未移动”的最小移动阈值(像素^2),例如 4px -> 16
23+ const MOVE_THRESHOLD_SQ = 16 ;
24+ let lastMouseX = 0 ;
25+ let lastMouseY = 0 ;
26+ let hasLastMousePos = false ;
6727
6828/**
6929 * 检查并更新控制可见性
@@ -79,22 +39,38 @@ function updateControlsVisibility(
7939 GUIState : IGuiState ,
8040 dispatch : ReturnType < typeof useDispatch > ,
8141) {
82- if ( isTextboxHidden ( stageState , GUIState ) ) {
83- // 当文本框被隐藏时
84- // 逻辑:鼠标移动时显示,一段时间(默认:1秒)后隐藏
85- if ( timeoutEventHandle ) {
86- clearTimeout ( timeoutEventHandle ) ;
87- }
42+ // 新逻辑:超过阈值的鼠标移动立刻显示,2s 无操作后隐藏(未锁定时)
43+ const { clientX, clientY } = event ;
44+ let movedEnough = false ;
45+ if ( ! hasLastMousePos ) {
46+ movedEnough = true ; // 第一次移动视为足够
47+ hasLastMousePos = true ;
48+ } else {
49+ const dx = clientX - lastMouseX ;
50+ const dy = clientY - lastMouseY ;
51+ movedEnough = dx * dx + dy * dy >= MOVE_THRESHOLD_SQ ;
52+ }
53+ lastMouseX = clientX ;
54+ lastMouseY = clientY ;
55+
56+ if ( ! movedEnough ) {
57+ // 微小移动,视为无操作,不重置计时器
58+ return ;
59+ }
60+
61+ if ( timeoutEventHandle ) {
62+ clearTimeout ( timeoutEventHandle ) ;
63+ }
8864
65+ if ( ! GUIState . controlsVisibility ) {
8966 dispatch ( setVisibility ( { component : 'controlsVisibility' , visibility : true } ) ) ;
90- timeoutEventHandle = setTimeout ( ( ) => {
91- dispatch ( setVisibility ( { component : 'controlsVisibility' , visibility : false } ) ) ;
92- } , 1000 ) ;
93- } else {
94- // 当文本框正常显示时
95- // 逻辑:鼠标位置在文本框内时显示
96- checkMousePosition ( event , GUIState , dispatch ) ;
9767 }
68+
69+ timeoutEventHandle = setTimeout ( ( ) => {
70+ if ( ! webgalStore . getState ( ) . GUI . showControls ) {
71+ dispatch ( setVisibility ( { component : 'controlsVisibility' , visibility : false } ) ) ;
72+ }
73+ } , 2000 ) ;
9874}
9975
10076export const Stage : FC = ( ) => {
0 commit comments