fix: 修复项目切换时运行时和系统重复初始化问题 (#267)
* feat(editor): 添加 GitHub Discussions 社区论坛功能 * chore: 更新 pnpm-lock.yaml * chore: 删除测试图片 * refactor: 改用 Imgur 图床上传图片 * fix: 修复项目切换时运行时和系统重复初始化问题 * fix: 修复多个编辑器问题 * feat: 添加脚本编辑器配置和类型定义支持 * feat: 实现资产 .meta 文件自动生成功能
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
||||
type GameRuntimeConfig
|
||||
} from '@esengine/runtime-core';
|
||||
import { getMaterialManager } from '@esengine/material-system';
|
||||
import { resetEngineState } from '../hooks/useEngine';
|
||||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import { IdGenerator } from '../utils/idGenerator';
|
||||
import { TauriAssetReader } from './TauriAssetReader';
|
||||
@@ -245,7 +246,14 @@ export class EngineService {
|
||||
ctx.uiInputSystem.unbind?.();
|
||||
}
|
||||
|
||||
// 清理 viewport | Clear viewport
|
||||
this.unregisterViewport('editor-viewport');
|
||||
|
||||
// 重置 useEngine 的模块级状态 | Reset useEngine module-level state
|
||||
resetEngineState();
|
||||
|
||||
this._modulesInitialized = false;
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,9 +70,11 @@ export class SettingsService {
|
||||
}
|
||||
|
||||
public addRecentProject(projectPath: string): void {
|
||||
// 规范化路径,防止双重转义 | Normalize path to prevent double escaping
|
||||
const normalizedPath = projectPath.replace(/\\\\/g, '\\');
|
||||
const recentProjects = this.getRecentProjects();
|
||||
const filtered = recentProjects.filter((p) => p !== projectPath);
|
||||
const updated = [projectPath, ...filtered].slice(0, 10);
|
||||
const filtered = recentProjects.filter((p) => p !== normalizedPath);
|
||||
const updated = [normalizedPath, ...filtered].slice(0, 10);
|
||||
this.set('recentProjects', updated);
|
||||
}
|
||||
|
||||
@@ -85,4 +87,64 @@ export class SettingsService {
|
||||
public clearRecentProjects(): void {
|
||||
this.set('recentProjects', []);
|
||||
}
|
||||
|
||||
// ==================== Script Editor Settings ====================
|
||||
|
||||
/**
|
||||
* 支持的脚本编辑器类型
|
||||
* Supported script editor types
|
||||
*/
|
||||
public static readonly SCRIPT_EDITORS = [
|
||||
{ id: 'system', name: 'System Default', nameZh: '系统默认', command: '' },
|
||||
{ id: 'vscode', name: 'Visual Studio Code', nameZh: 'Visual Studio Code', command: 'code' },
|
||||
{ id: 'cursor', name: 'Cursor', nameZh: 'Cursor', command: 'cursor' },
|
||||
{ id: 'webstorm', name: 'WebStorm', nameZh: 'WebStorm', command: 'webstorm' },
|
||||
{ id: 'sublime', name: 'Sublime Text', nameZh: 'Sublime Text', command: 'subl' },
|
||||
{ id: 'custom', name: 'Custom', nameZh: '自定义', command: '' }
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取脚本编辑器设置
|
||||
* Get script editor setting
|
||||
*/
|
||||
public getScriptEditor(): string {
|
||||
return this.get<string>('editor.scriptEditor', 'system');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置脚本编辑器
|
||||
* Set script editor
|
||||
*/
|
||||
public setScriptEditor(editorId: string): void {
|
||||
this.set('editor.scriptEditor', editorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义脚本编辑器命令
|
||||
* Get custom script editor command
|
||||
*/
|
||||
public getCustomScriptEditorCommand(): string {
|
||||
return this.get<string>('editor.customScriptEditorCommand', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义脚本编辑器命令
|
||||
* Set custom script editor command
|
||||
*/
|
||||
public setCustomScriptEditorCommand(command: string): void {
|
||||
this.set('editor.customScriptEditorCommand', command);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前脚本编辑器的命令
|
||||
* Get current script editor command
|
||||
*/
|
||||
public getScriptEditorCommand(): string {
|
||||
const editorId = this.getScriptEditor();
|
||||
if (editorId === 'custom') {
|
||||
return this.getCustomScriptEditorCommand();
|
||||
}
|
||||
const editor = SettingsService.SCRIPT_EDITORS.find(e => e.id === editorId);
|
||||
return editor?.command || '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,19 @@ export class TauriFileSystemService implements IFileSystem {
|
||||
|
||||
async exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await invoke('read_file_content', { path });
|
||||
// 首先尝试作为目录列出内容
|
||||
// First try to list as directory
|
||||
await invoke('list_directory', { path });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
// 如果不是目录,尝试读取文件
|
||||
// If not a directory, try reading as file
|
||||
try {
|
||||
await invoke('read_file_content', { path });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +43,19 @@ export class TauriFileSystemService implements IFileSystem {
|
||||
}
|
||||
|
||||
async listDirectory(path: string): Promise<FileEntry[]> {
|
||||
const entries = await invoke<Array<{ name: string; path: string; is_dir: boolean }>>('list_directory', { path });
|
||||
const entries = await invoke<Array<{
|
||||
name: string;
|
||||
path: string;
|
||||
is_dir: boolean;
|
||||
size?: number;
|
||||
modified?: number;
|
||||
}>>('list_directory', { path });
|
||||
return entries.map((entry) => ({
|
||||
name: entry.name,
|
||||
isDirectory: entry.is_dir,
|
||||
path: entry.path
|
||||
path: entry.path,
|
||||
size: entry.size,
|
||||
modified: entry.modified ? new Date(entry.modified * 1000) : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user