位置:src/utils/fileOperations.ts
功能:
- ✅ 新建项目:清空当前项目创建新项目
- ✅ 保存项目:保存到当前文件路径(
.w3ui格式) - ✅ 另存为:选择新路径保存项目
- ✅ 打开项目:从文件加载项目 JSON 数据
使用 Tauri 插件:
@tauri-apps/plugin-dialog:文件对话框@tauri-apps/plugin-fs:文件系统读写
位置:src/utils/codeExport.ts
支持的导出格式:
- ✅ JASS:魔兽争霸 3 原生脚本语言
- ✅ Lua:Lua 5.3 脚本(重制版支持)
- ✅ TypeScript:面向对象的 TS 类封装
导出内容包含:
- Frame 声明(全局变量/类属性)
- Frame 创建代码(BlzCreateFrame 调用)
- 位置和大小设置(BlzFrameSetAbsPoint, BlzFrameSetSize)
- 纹理应用(BlzFrameSetTexture)
- 文本内容和样式(BlzFrameSetText, BlzFrameSetScale)
- 完整的库初始化代码
代码模板:
// JASS 示例
library UILib initializer Init
globals
framehandle myBackdrop = null
endglobals
function CreateFrames takes nothing returns nothing
set myBackdrop = BlzCreateFrame("BACKDROP", ...)
call BlzFrameSetAbsPoint(myBackdrop, ...)
endfunction
-- Lua 示例
myBackdrop = BlzCreateFrame("BACKDROP", ...)
BlzFrameSetAbsPoint(myBackdrop, ...)// TypeScript 示例
export class UILib {
private myBackdrop: framehandle | null = null;
constructor() {
this.createFrames();
}
}位置:src/components/Canvas.tsx
功能:
- ✅ Frame 拖拽移动:左键拖拽 Frame 到新位置
- ✅ 画布平移:Alt + 拖拽 或 鼠标中键拖拽整个画布
- ✅ 缩放控制:Alt + 鼠标滚轮缩放画布(10% - 500%)
- ✅ 边界限制:Frame 不会移出 0.8 x 0.6 魔兽坐标范围
- ✅ 实时预览:拖拽时即时更新 Frame 位置
交互说明:
- 左键点击 Frame:选中 Frame
- 左键拖拽 Frame:移动 Frame 位置
- Alt + 左键拖拽背景:平移整个画布
- Alt + 鼠标滚轮:缩放画布视图
- 点击背景空白处:取消选择
位置:src/commands/FrameCommands.ts
已实现的命令:
- ✅
CreateFrameCommand:创建 Frame - ✅
RemoveFrameCommand:删除 Frame - ✅
UpdateFrameCommand:更新 Frame 属性(含拖拽) - ✅
MoveFrameCommand:移动 Frame(含父子关系) - ✅
ChangeParentCommand:修改父级关系
特性:
- 完整的 Undo/Redo 支持
- 支持 Ctrl+Z / Ctrl+Y 快捷键
- 保存每个操作的前后状态
- 拖拽移动自动记录到历史
位置:src/components/Toolbar.tsx
- 📄 新建:
handleNewProject()- 创建新项目 - 📂 打开:
handleLoad()- 加载 .w3ui 文件 - 💾 保存:
handleSave()- 保存到当前路径(首次自动另存为) - 💾 另存为:
handleSaveAs()- 选择新路径保存
- 📤 JASS:
handleExport('jass')- 导出 JASS 代码 - 📤 Lua:
handleExport('lua')- 导出 Lua 代码 - 📤 TS:
handleExport('ts')- 导出 TypeScript 代码
- ↶ 撤销:
undo()- Ctrl+Z - ↷ 重做:
redo()- Ctrl+Y
- ▭ Backdrop:创建背景 Frame
- 🔘 Button:创建按钮 Frame
- T Text:创建文本 Frame
- ☑ Checkbox:创建复选框 Frame
- ✅ 完整的类型系统(19 种 Frame 类型)
- ✅ Zustand 全局状态管理
- ✅ 命令模式(5 种命令,完整撤销/重做)
- ✅ 4 个主要 UI 组件(Canvas, Toolbar, Tree, Properties)
- ✅ 文件保存/加载系统
- ✅ 三语言代码导出(JASS/Lua/TS)
- ✅ Canvas 拖拽交互
- ✅ 缩放和平移控制
-
Frame 调整大小
- 添加拖拽手柄(8个方向)
- 鼠标拖拽边角调整 width/height
- 保持纵横比选项(Shift 键)
-
更多导出选项
- 完善其他 Frame 类型的代码生成(EDITBOX, SLIDER 等)
- 支持父子层级关系代码生成
- 触发器变量导出
-
快捷键系统
- Ctrl+S 保存
- Ctrl+N 新建
- Ctrl+O 打开
- Delete 删除选中 Frame
- Ctrl+D 复制 Frame
-
数组系统 UI
- TableArray 创建对话框
- CircleArray 创建对话框
- 数组元素可视化预览
-
属性面板增强
- 颜色选择器(textColor)
- 文件选择器(纹理路径)
- 坐标精确输入(数字输入框)
-
项目树增强
- 拖拽排序
- 拖拽修改父子关系
- 右键菜单(复制/粘贴/删除)
-
图像格式支持
- BLP/DDS 图像预览(需要解析器)
- 纹理库管理
- 拖拽图片到 Frame
-
多语言支持
- 界面中英文切换
- 导出代码注释本地化
-
模板系统
- 常用 UI 组件模板
- 模板库导入/导出
- 社区模板分享
# 1. 启动开发服务器
npm run tauri dev
# 2. 在应用中:
# - 点击"新建"创建项目
# - 添加几个 Frame(Backdrop, Text 等)
# - 点击"另存为"保存为 test.w3ui
# - 点击"打开"重新加载 test.w3ui# 在应用中:
# 1. 创建一些 Frame
# 2. 点击"JASS"导出
# 3. 选择保存路径(如 ui_export.j)
# 4. 用文本编辑器打开查看生成的代码# 在应用中:
# 1. 创建一个 Backdrop Frame
# 2. 在 Canvas 上用鼠标左键拖拽移动它
# 3. 按住 Alt 键 + 鼠标左键拖拽画布平移
# 4. 按住 Alt 键 + 滚动鼠标滚轮缩放
# 5. 点击"撤销"恢复移动前的位置- ✅ 创建文件操作系统(fileOperations.ts)
- ✅ 创建代码导出系统(codeExport.ts)
- ✅ 集成 Toolbar 文件和导出功能
- ✅ 增强 Canvas 拖拽交互
- ✅ 修复所有 TypeScript 编译错误
- ✅ 测试撤销/重做与拖拽的集成
Tauri 文件 API 使用:
import { save, open } from '@tauri-apps/plugin-dialog';
import { writeTextFile, readTextFile } from '@tauri-apps/plugin-fs';
// 保存文件
const path = await save({ filters: [{ name: 'WC3 UI', extensions: ['w3ui'] }] });
await writeTextFile(path, JSON.stringify(data));
// 读取文件
const path = await open({ filters: [{ name: 'WC3 UI', extensions: ['w3ui'] }] });
const content = await readTextFile(path);拖拽实现:
// 1. 鼠标按下:记录开始拖拽
const handleFrameMouseDown = (e, frameId) => {
setIsDraggingFrame(true);
setDraggedFrameId(frameId);
};
// 2. 鼠标移动:计算新位置
const handleMouseMove = (e) => {
const mouseX = (e.clientX - canvasBounds.left) / scale;
const mouseY = (canvasBounds.bottom - e.clientY) / scale;
const newX = ((mouseX - MARGIN) / (WIDTH - 2*MARGIN)) * 0.8;
const newY = (mouseY / HEIGHT) * 0.6;
executeCommand(new UpdateFrameCommand(frameId, { x: newX, y: newY }));
};
// 3. 鼠标释放:结束拖拽
const handleMouseUp = () => {
setIsDraggingFrame(false);
};用户操作 → Command → CommandStore.execute()
↓
ProjectStore.setState()
↓
React 组件自动更新(Zustand 订阅)
.w3ui 文件是 JSON 格式:
{
"libraryName": "UILib",
"originMode": "gameui",
"hideGameUI": false,
"frames": {
"frame_id_1": {
"id": "frame_id_1",
"name": "MyBackdrop",
"type": 1,
"x": 0.1,
"y": 0.1,
"width": 0.2,
"height": 0.15,
...
}
},
"rootFrameIds": ["frame_id_1"],
"tableArrays": [],
"circleArrays": []
}- 魔兽 3 坐标:左下角为原点,X: 0-0.8, Y: 0-0.6(4:3 安全区)
- Canvas 像素:1920x1080,边距 240px(模拟 16:9 屏幕)
- 转换公式:
canvasX = (wc3X / 0.8) * (1920 - 480) + 240 canvasY = (wc3Y / 0.6) * 1080
祝开发顺利!🚀