feat: 更新大版本
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 14px;
|
||||||
|
background: rgba(8, 8, 8, 0.92);
|
||||||
|
pointer-events: auto;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.28s ease-out, visibility 0.28s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #f2f2f2;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.5;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.barTrack {
|
||||||
|
width: min(72%, 280px);
|
||||||
|
height: 10px;
|
||||||
|
background: rgba(255, 255, 255, 0.16);
|
||||||
|
border-radius: 999px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.barFill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #4fc3f7 0%, #29b6f6 100%);
|
||||||
|
border-radius: 999px;
|
||||||
|
transition: width 0.25s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.percent {
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import styles from './game-loading-overlay.css';
|
||||||
|
|
||||||
|
const GameLoadingOverlay = ({ visible, progress }) => {
|
||||||
|
const pct = Math.max(0, Math.min(100, Math.round(Number(progress) || 0)));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${styles.overlay}${visible ? '' : ` ${styles.hidden}`}`}
|
||||||
|
aria-hidden={!visible}
|
||||||
|
>
|
||||||
|
<div className={styles.text}>正在加载中</div>
|
||||||
|
<div className={styles.barTrack}>
|
||||||
|
<div className={styles.barFill} style={{ width: `${pct}%` }} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.percent}>{pct}%</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
GameLoadingOverlay.propTypes = {
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
progress: PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
GameLoadingOverlay.defaultProps = {
|
||||||
|
visible: true,
|
||||||
|
progress: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GameLoadingOverlay;
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
const alreadyReady = () => typeof window !== 'undefined' && window.iscreate === 1;
|
||||||
|
|
||||||
|
const useGameLoadProgress = () => {
|
||||||
|
const [progress, setProgress] = useState(() => (alreadyReady() ? 100 : 0));
|
||||||
|
const [visible, setVisible] = useState(() => !alreadyReady());
|
||||||
|
const hidingRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible) return undefined;
|
||||||
|
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
if (window.iscreate === 1) {
|
||||||
|
if (!hidingRef.current) {
|
||||||
|
hidingRef.current = true;
|
||||||
|
setProgress(100);
|
||||||
|
setTimeout(() => setVisible(false), 280);
|
||||||
|
}
|
||||||
|
clearInterval(timer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setProgress(prev => (prev >= 90 && prev < 99 ? prev + 1 : prev));
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
const onUnityProgress = useCallback(unityProgress => {
|
||||||
|
const mapped = Math.round(Math.min(90, Number(unityProgress) * 90));
|
||||||
|
if (!Number.isFinite(mapped)) return;
|
||||||
|
setProgress(prev => (mapped > prev ? mapped : prev));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onUnityInstanceCreated = useCallback(() => {
|
||||||
|
setProgress(prev => Math.max(prev, 90));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
progress,
|
||||||
|
visible,
|
||||||
|
onUnityProgress,
|
||||||
|
onUnityInstanceCreated
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGameLoadProgress;
|
||||||
@@ -15,6 +15,8 @@ import disableDevtool from 'disable-devtool';
|
|||||||
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
||||||
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
||||||
import { debug } from 'scratch-vm/src/util/log.js';
|
import { debug } from 'scratch-vm/src/util/log.js';
|
||||||
|
import GameLoadingOverlay from '../game-loading-overlay/game-loading-overlay.jsx';
|
||||||
|
import useGameLoadProgress from '../game-loading-overlay/use-game-load-progress.js';
|
||||||
|
|
||||||
const MAX_LEVELS = 500; // 最大关卡数据数量
|
const MAX_LEVELS = 500; // 最大关卡数据数量
|
||||||
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
||||||
@@ -48,6 +50,16 @@ const UnityComponent = function (props) {
|
|||||||
const [getBlockNum, setBlockNum] = useState(0);
|
const [getBlockNum, setBlockNum] = useState(0);
|
||||||
const [testDal, setTestDal] = useState(-1);
|
const [testDal, setTestDal] = useState(-1);
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
|
const {
|
||||||
|
progress: gameLoadProgress,
|
||||||
|
visible: gameLoadVisible,
|
||||||
|
onUnityProgress,
|
||||||
|
onUnityInstanceCreated
|
||||||
|
} = useGameLoadProgress();
|
||||||
|
const onUnityProgressRef = useRef(onUnityProgress);
|
||||||
|
const onUnityInstanceCreatedRef = useRef(onUnityInstanceCreated);
|
||||||
|
onUnityProgressRef.current = onUnityProgress;
|
||||||
|
onUnityInstanceCreatedRef.current = onUnityInstanceCreated;
|
||||||
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
||||||
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
||||||
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
||||||
@@ -1274,8 +1286,9 @@ const UnityComponent = function (props) {
|
|||||||
window.iscreate = 0;
|
window.iscreate = 0;
|
||||||
const boot = () => {
|
const boot = () => {
|
||||||
createUnityInstance(canvas, config, (progress) => {
|
createUnityInstance(canvas, config, (progress) => {
|
||||||
// console.log(`加载进度: ${progress * 100}%`);
|
onUnityProgressRef.current(progress);
|
||||||
}).then((unityInstance) => {
|
}).then((unityInstance) => {
|
||||||
|
onUnityInstanceCreatedRef.current();
|
||||||
window.unityInstance = unityInstance;
|
window.unityInstance = unityInstance;
|
||||||
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
||||||
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
||||||
@@ -1339,6 +1352,7 @@ const UnityComponent = function (props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
||||||
|
<GameLoadingOverlay visible={gameLoadVisible} progress={gameLoadProgress} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1160,12 +1160,13 @@ const StageWrapperCppClang = () => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!isApiPanelReady && (
|
<div
|
||||||
<div className={styles.apiDrawerLoading}>
|
className={`${styles.apiDrawerLoading}${isApiPanelReady ? ` ${styles.apiDrawerLoadingHidden}` : ''}`}
|
||||||
<div className={styles.apiDrawerLoadingSpinner}></div>
|
aria-hidden={isApiPanelReady}
|
||||||
<div className={styles.apiDrawerLoadingText}>游戏引擎加载中,完成后即可插入代码…</div>
|
>
|
||||||
</div>
|
<div className={styles.apiDrawerLoadingSpinner}></div>
|
||||||
)}
|
<div className={styles.apiDrawerLoadingText}>正在加载中,完成后即可插入代码…</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1186,6 +1187,12 @@ const StageWrapperCppClang = () => {
|
|||||||
// 移除snippet标记,转换为普通文本
|
// 移除snippet标记,转换为普通文本
|
||||||
insertCode = code.replace(/#{([^}]*)}/g, '$1');
|
insertCode = code.replace(/#{([^}]*)}/g, '$1');
|
||||||
}
|
}
|
||||||
|
if (cursor > 0 && view.state.doc.sliceString(cursor - 1, cursor) !== '\n') {
|
||||||
|
insertCode = '\n' + insertCode;
|
||||||
|
}
|
||||||
|
if (!insertCode.endsWith('\n')) {
|
||||||
|
insertCode += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
// 插入代码
|
// 插入代码
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
@@ -1210,7 +1217,7 @@ const StageWrapperCppClang = () => {
|
|||||||
<CompilationModal />
|
<CompilationModal />
|
||||||
<SyntaxErrorModal />
|
<SyntaxErrorModal />
|
||||||
<div className={styles.editorWithApi}>
|
<div className={styles.editorWithApi}>
|
||||||
<ApiDrawer />
|
{ApiDrawer()}
|
||||||
<div
|
<div
|
||||||
className={styles.editorPane}
|
className={styles.editorPane}
|
||||||
onWheel={(e) => e.stopPropagation()}
|
onWheel={(e) => e.stopPropagation()}
|
||||||
|
|||||||
@@ -531,6 +531,10 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apiDrawerLoadingHidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.apiDrawerLoadingSpinner {
|
.apiDrawerLoadingSpinner {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
@@ -538,6 +542,7 @@
|
|||||||
border-top-color: #ba68c8;
|
border-top-color: #ba68c8;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: apiDrawerLoadingSpin 0.9s linear infinite;
|
animation: apiDrawerLoadingSpin 0.9s linear infinite;
|
||||||
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.apiDrawerLoadingText {
|
.apiDrawerLoadingText {
|
||||||
@@ -549,6 +554,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes apiDrawerLoadingSpin {
|
@keyframes apiDrawerLoadingSpin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import disableDevtool from 'disable-devtool';
|
|||||||
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
||||||
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
||||||
import { debug } from 'scratch-vm/src/util/log.js';
|
import { debug } from 'scratch-vm/src/util/log.js';
|
||||||
|
import GameLoadingOverlay from '../game-loading-overlay/game-loading-overlay.jsx';
|
||||||
|
import useGameLoadProgress from '../game-loading-overlay/use-game-load-progress.js';
|
||||||
|
|
||||||
const MAX_LEVELS = 500; // 最大关卡数据数量
|
const MAX_LEVELS = 500; // 最大关卡数据数量
|
||||||
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
||||||
@@ -48,6 +50,16 @@ const UnityComponent = function (props) {
|
|||||||
const [getBlockNum, setBlockNum] = useState(0);
|
const [getBlockNum, setBlockNum] = useState(0);
|
||||||
const [testDal, setTestDal] = useState(-1);
|
const [testDal, setTestDal] = useState(-1);
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
|
const {
|
||||||
|
progress: gameLoadProgress,
|
||||||
|
visible: gameLoadVisible,
|
||||||
|
onUnityProgress,
|
||||||
|
onUnityInstanceCreated
|
||||||
|
} = useGameLoadProgress();
|
||||||
|
const onUnityProgressRef = useRef(onUnityProgress);
|
||||||
|
const onUnityInstanceCreatedRef = useRef(onUnityInstanceCreated);
|
||||||
|
onUnityProgressRef.current = onUnityProgress;
|
||||||
|
onUnityInstanceCreatedRef.current = onUnityInstanceCreated;
|
||||||
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
||||||
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
||||||
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
||||||
@@ -1259,8 +1271,9 @@ const UnityComponent = function (props) {
|
|||||||
window.iscreate = 0;
|
window.iscreate = 0;
|
||||||
const boot = () => {
|
const boot = () => {
|
||||||
createUnityInstance(canvas, config, (progress) => {
|
createUnityInstance(canvas, config, (progress) => {
|
||||||
// console.log(`加载进度: ${progress * 100}%`);
|
onUnityProgressRef.current(progress);
|
||||||
}).then((unityInstance) => {
|
}).then((unityInstance) => {
|
||||||
|
onUnityInstanceCreatedRef.current();
|
||||||
window.unityInstance = unityInstance;
|
window.unityInstance = unityInstance;
|
||||||
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
||||||
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
||||||
@@ -1324,6 +1337,7 @@ const UnityComponent = function (props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
||||||
|
<GameLoadingOverlay visible={gameLoadVisible} progress={gameLoadProgress} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,10 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apiDrawerLoadingHidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.apiDrawerLoadingSpinner {
|
.apiDrawerLoadingSpinner {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
@@ -190,6 +194,7 @@
|
|||||||
border-top-color: #ba68c8;
|
border-top-color: #ba68c8;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: apiDrawerLoadingSpin 0.9s linear infinite;
|
animation: apiDrawerLoadingSpin 0.9s linear infinite;
|
||||||
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.apiDrawerLoadingText {
|
.apiDrawerLoadingText {
|
||||||
@@ -201,6 +206,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes apiDrawerLoadingSpin {
|
@keyframes apiDrawerLoadingSpin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1287,12 +1287,13 @@ sys.settrace(trace_func)`;
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!isApiPanelReady && (
|
<div
|
||||||
<div className={styles.apiDrawerLoading}>
|
className={`${styles.apiDrawerLoading}${isApiPanelReady ? ` ${styles.apiDrawerLoadingHidden}` : ''}`}
|
||||||
<div className={styles.apiDrawerLoadingSpinner}></div>
|
aria-hidden={isApiPanelReady}
|
||||||
<div className={styles.apiDrawerLoadingText}>游戏引擎加载中,完成后即可插入代码…</div>
|
>
|
||||||
</div>
|
<div className={styles.apiDrawerLoadingSpinner}></div>
|
||||||
)}
|
<div className={styles.apiDrawerLoadingText}>正在加载中,完成后即可插入代码…</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1305,12 +1306,22 @@ sys.settrace(trace_func)`;
|
|||||||
const { state } = view;
|
const { state } = view;
|
||||||
const { selection } = state;
|
const { selection } = state;
|
||||||
const cursor = selection.main.head;
|
const cursor = selection.main.head;
|
||||||
|
const withSafeNewlines = (text) => {
|
||||||
|
let next = text;
|
||||||
|
if (cursor > 0 && view.state.doc.sliceString(cursor - 1, cursor) !== '\n') {
|
||||||
|
next = '\n' + next;
|
||||||
|
}
|
||||||
|
if (!next.endsWith('\n')) {
|
||||||
|
next += '\n';
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
// 检查代码是否包含snippet占位符
|
// 检查代码是否包含snippet占位符
|
||||||
if (code.includes('#{')) {
|
if (code.includes('#{')) {
|
||||||
// 使用snippet功能插入代码
|
// 使用snippet功能插入代码
|
||||||
try {
|
try {
|
||||||
const snippetTemplate = snippet(code);
|
const snippetTemplate = snippet(withSafeNewlines(code));
|
||||||
const completion = snippetTemplate(view, {
|
const completion = snippetTemplate(view, {
|
||||||
from: cursor,
|
from: cursor,
|
||||||
to: cursor
|
to: cursor
|
||||||
@@ -1320,7 +1331,7 @@ sys.settrace(trace_func)`;
|
|||||||
view.dispatch(completion);
|
view.dispatch(completion);
|
||||||
} else {
|
} else {
|
||||||
// 如果snippet创建失败,使用简化的插入方式
|
// 如果snippet创建失败,使用简化的插入方式
|
||||||
const cleanCode = code.replace(/#{([^}]*)}/g, '$1');
|
const cleanCode = withSafeNewlines(code.replace(/#{([^}]*)}/g, '$1'));
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
from: cursor,
|
from: cursor,
|
||||||
@@ -1332,7 +1343,7 @@ sys.settrace(trace_func)`;
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Snippet insertion failed, falling back to plain text:', error);
|
console.warn('Snippet insertion failed, falling back to plain text:', error);
|
||||||
// 回退到普通插入,移除snippet标记
|
// 回退到普通插入,移除snippet标记
|
||||||
const cleanCode = code.replace(/#{([^}]*)}/g, '$1');
|
const cleanCode = withSafeNewlines(code.replace(/#{([^}]*)}/g, '$1'));
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
from: cursor,
|
from: cursor,
|
||||||
@@ -1342,15 +1353,15 @@ sys.settrace(trace_func)`;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 普通代码插入
|
const insertText = withSafeNewlines(code);
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
from: cursor,
|
from: cursor,
|
||||||
to: cursor,
|
to: cursor,
|
||||||
insert: code
|
insert: insertText
|
||||||
},
|
},
|
||||||
selection: {
|
selection: {
|
||||||
anchor: cursor + code.length
|
anchor: cursor + insertText.length
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1365,7 +1376,7 @@ sys.settrace(trace_func)`;
|
|||||||
<>
|
<>
|
||||||
<ErrorModal />
|
<ErrorModal />
|
||||||
<div className={styles.editorWithApi}>
|
<div className={styles.editorWithApi}>
|
||||||
<ApiDrawer />
|
{ApiDrawer()}
|
||||||
<div
|
<div
|
||||||
className={styles.editorPane}
|
className={styles.editorPane}
|
||||||
onWheel={(e) => e.stopPropagation()}
|
onWheel={(e) => e.stopPropagation()}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import disableDevtool from 'disable-devtool';
|
|||||||
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
import { initDisableDevtool } from '../../playground/devtool-control.js';
|
||||||
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
import { getUnityPlayerConfig, loadUnityLoaderScript } from '../../lib/unity-build-loader.js';
|
||||||
import { debug } from 'scratch-vm/src/util/log.js';
|
import { debug } from 'scratch-vm/src/util/log.js';
|
||||||
|
import GameLoadingOverlay from '../game-loading-overlay/game-loading-overlay.jsx';
|
||||||
|
import useGameLoadProgress from '../game-loading-overlay/use-game-load-progress.js';
|
||||||
|
|
||||||
const MAX_LEVELS = 500; // 最大关卡数据数量
|
const MAX_LEVELS = 500; // 最大关卡数据数量
|
||||||
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
const STORAGE_KEY = 'player_levels_data'; // 使用命名空间,防止键名冲突
|
||||||
@@ -248,6 +250,16 @@ const UnityComponent = function (props) {
|
|||||||
const [getBlockNum, setBlockNum] = useState(0);
|
const [getBlockNum, setBlockNum] = useState(0);
|
||||||
const [testDal, setTestDal] = useState(-1);
|
const [testDal, setTestDal] = useState(-1);
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
|
const {
|
||||||
|
progress: gameLoadProgress,
|
||||||
|
visible: gameLoadVisible,
|
||||||
|
onUnityProgress,
|
||||||
|
onUnityInstanceCreated
|
||||||
|
} = useGameLoadProgress();
|
||||||
|
const onUnityProgressRef = useRef(onUnityProgress);
|
||||||
|
const onUnityInstanceCreatedRef = useRef(onUnityInstanceCreated);
|
||||||
|
onUnityProgressRef.current = onUnityProgress;
|
||||||
|
onUnityInstanceCreatedRef.current = onUnityInstanceCreated;
|
||||||
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
const [isGameOverVisible, setIsGameOverVisible] = useState(false);
|
||||||
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
const [isGameOkVisible, setIsGameOkVisible] = useState(false);
|
||||||
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
const [isLockNextButton, setIsLockNextButton] = useState(true);
|
||||||
@@ -1522,8 +1534,9 @@ const UnityComponent = function (props) {
|
|||||||
window.iscreate = 0;
|
window.iscreate = 0;
|
||||||
const boot = () => {
|
const boot = () => {
|
||||||
createUnityInstance(canvas, config, (progress) => {
|
createUnityInstance(canvas, config, (progress) => {
|
||||||
// console.log(`加载进度: ${progress * 100}%`);
|
onUnityProgressRef.current(progress);
|
||||||
}).then((unityInstance) => {
|
}).then((unityInstance) => {
|
||||||
|
onUnityInstanceCreatedRef.current();
|
||||||
window.unityInstance = unityInstance;
|
window.unityInstance = unityInstance;
|
||||||
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
window.waitForUnityStepFinish = waitForUnityStepFinish;
|
||||||
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
window.waitForUnityVehicleStepFinish = waitForUnityVehicleStepFinish;
|
||||||
@@ -1587,6 +1600,7 @@ const UnityComponent = function (props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
<canvas id="unity-canvas" ref={canvasRef} width="960" height="600" style={{ width: '100%', height: '100%' }}></canvas>
|
||||||
|
<GameLoadingOverlay visible={gameLoadVisible} progress={gameLoadProgress} />
|
||||||
|
|
||||||
<section
|
<section
|
||||||
className="u-align-center u-black u-clearfix u-container-align-center u-container-style u-dialog-block u-opacity u-opacity-50 u-valign-middle-md u-valign-middle-xl u-dialog-section-8"
|
className="u-align-center u-black u-clearfix u-container-align-center u-container-style u-dialog-block u-opacity u-opacity-50 u-valign-middle-md u-valign-middle-xl u-dialog-section-8"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user