核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
226 lines
7.4 KiB
C
226 lines
7.4 KiB
C
// ============================================================================
|
|
// block_editor.c - 编辑器主界面实现
|
|
// ============================================================================
|
|
|
|
#include "block_editor.h"
|
|
#include "block_types.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
int block_editor_init(BlockEditor* editor, void* device, void* context, int width, int height) {
|
|
memset(editor, 0, sizeof(BlockEditor));
|
|
|
|
editor->width = width;
|
|
editor->height = height;
|
|
editor->toolbar_height = 30;
|
|
editor->properties_width = 200;
|
|
editor->visible = 0;
|
|
|
|
// 创建工作区
|
|
editor->workspace = workspace_create();
|
|
if (!editor->workspace) return 0;
|
|
|
|
// 初始化渲染器
|
|
if (!block_renderer_init(&editor->renderer, device, context)) {
|
|
workspace_destroy(editor->workspace);
|
|
return 0;
|
|
}
|
|
|
|
// 初始化交互
|
|
interaction_init(&editor->interaction);
|
|
|
|
// 初始化面板
|
|
palette_init(&editor->palette);
|
|
editor->palette.x = 0;
|
|
editor->palette.y = editor->toolbar_height;
|
|
|
|
// 创建执行器
|
|
editor->executor = executor_create(editor->workspace);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void block_editor_shutdown(BlockEditor* editor) {
|
|
if (editor->executor) executor_destroy(editor->executor);
|
|
block_renderer_shutdown(&editor->renderer);
|
|
if (editor->workspace) workspace_destroy(editor->workspace);
|
|
}
|
|
|
|
void block_editor_show(BlockEditor* editor) {
|
|
editor->visible = 1;
|
|
}
|
|
|
|
void block_editor_hide(BlockEditor* editor) {
|
|
editor->visible = 0;
|
|
}
|
|
|
|
int block_editor_is_visible(BlockEditor* editor) {
|
|
return editor->visible;
|
|
}
|
|
|
|
void block_editor_update(BlockEditor* editor, double delta_time) {
|
|
if (!editor->visible) return;
|
|
|
|
// 更新交互
|
|
interaction_update(&editor->interaction, editor->workspace);
|
|
|
|
// 更新执行器
|
|
if (editor->executor->state == EXEC_RUNNING) {
|
|
executor_update(editor->executor, delta_time);
|
|
}
|
|
}
|
|
|
|
void block_editor_render(BlockEditor* editor) {
|
|
if (!editor->visible) return;
|
|
|
|
block_renderer_begin(&editor->renderer);
|
|
|
|
// 绘制工具栏
|
|
block_renderer_add_quad(&editor->renderer, 0, 0, (float)editor->width, (float)editor->toolbar_height,
|
|
0.2f, 0.2f, 0.25f, 1.0f);
|
|
block_renderer_draw_text(&editor->renderer, "积木编辑器", 5, 5, 1.0f, 1.0f, 1.0f);
|
|
|
|
// 绘制面板
|
|
palette_render(&editor->palette, &editor->renderer);
|
|
|
|
// 绘制工作区积木
|
|
float ws_x = editor->palette.width;
|
|
float ws_y = editor->toolbar_height;
|
|
float ws_w = (float)editor->width - editor->palette.width - editor->properties_width;
|
|
float ws_h = (float)editor->height - editor->toolbar_height;
|
|
|
|
// 工作区背景
|
|
block_renderer_add_quad(&editor->renderer, ws_x, ws_y, ws_w, ws_h,
|
|
0.12f, 0.12f, 0.15f, 1.0f);
|
|
|
|
// 绘制连接线
|
|
for (int i = 0; i < editor->workspace->connection_count; i++) {
|
|
BlockConnection* conn = &editor->workspace->connections[i];
|
|
if (conn->from && conn->to) {
|
|
block_renderer_draw_connection(&editor->renderer, conn->from, conn->to,
|
|
editor->workspace->view_x, editor->workspace->view_y, editor->workspace->zoom);
|
|
}
|
|
}
|
|
|
|
// 绘制积木
|
|
for (int i = 0; i < editor->workspace->block_count; i++) {
|
|
Block* block = editor->workspace->blocks[i];
|
|
block_renderer_draw_block(&editor->renderer, block,
|
|
editor->workspace->view_x, editor->workspace->view_y, editor->workspace->zoom);
|
|
|
|
// 高亮选中的积木
|
|
if (block == editor->workspace->selected_block) {
|
|
float x = (block->x - editor->workspace->view_x) * editor->workspace->zoom;
|
|
float y = (block->y - editor->workspace->view_y) * editor->workspace->zoom;
|
|
float w = block->width * editor->workspace->zoom;
|
|
float h = block->height * editor->workspace->zoom;
|
|
block_renderer_add_quad(&editor->renderer, x - 2, y - 2, w + 4, h + 4,
|
|
1.0f, 1.0f, 0.0f, 0.3f);
|
|
}
|
|
}
|
|
|
|
// 绘制正在拖拽的连接线
|
|
if (editor->interaction.connecting_from) {
|
|
float x1, y1;
|
|
block_slot_world_pos(editor->interaction.connecting_from, &x1, &y1);
|
|
x1 = (x1 - editor->workspace->view_x) * editor->workspace->zoom;
|
|
y1 = (y1 - editor->workspace->view_y) * editor->workspace->zoom;
|
|
float x2 = (float)editor->interaction.mouse_x;
|
|
float y2 = (float)editor->interaction.mouse_y;
|
|
block_renderer_add_line(&editor->renderer, x1, y1, x2, y2, 1.0f, 1.0f, 0.0f, 0.8f);
|
|
}
|
|
|
|
block_renderer_end(&editor->renderer);
|
|
}
|
|
|
|
void block_editor_on_mouse_move(BlockEditor* editor, int x, int y) {
|
|
if (!editor->visible) return;
|
|
interaction_mouse_move(&editor->interaction, editor->workspace, x, y);
|
|
}
|
|
|
|
void block_editor_on_mouse_down(BlockEditor* editor, int button) {
|
|
if (!editor->visible) return;
|
|
|
|
int x = editor->interaction.mouse_x;
|
|
int y = editor->interaction.mouse_y;
|
|
|
|
// 检查面板点击
|
|
if (x < editor->palette.width && y >= editor->toolbar_height) {
|
|
BlockType type = palette_handle_click(&editor->palette, (float)x, (float)y);
|
|
if (type >= 0) {
|
|
block_editor_create_block_from_palette(editor, type, 300, 100);
|
|
}
|
|
return;
|
|
}
|
|
|
|
interaction_mouse_down(&editor->interaction, editor->workspace, button);
|
|
}
|
|
|
|
void block_editor_on_mouse_up(BlockEditor* editor, int button) {
|
|
if (!editor->visible) return;
|
|
interaction_mouse_up(&editor->interaction, editor->workspace, button);
|
|
}
|
|
|
|
void block_editor_on_mouse_wheel(BlockEditor* editor, int delta) {
|
|
if (!editor->visible) return;
|
|
interaction_mouse_wheel(&editor->interaction, editor->workspace, delta);
|
|
}
|
|
|
|
void block_editor_on_key(BlockEditor* editor, int key) {
|
|
if (!editor->visible) return;
|
|
interaction_key_down(&editor->interaction, editor->workspace, key);
|
|
}
|
|
|
|
void block_editor_on_resize(BlockEditor* editor, int width, int height) {
|
|
editor->width = width;
|
|
editor->height = height;
|
|
}
|
|
|
|
void block_editor_create_block_from_palette(BlockEditor* editor, BlockType type, float x, float y) {
|
|
Block* block = block_create(type, x, y);
|
|
if (!block) return;
|
|
|
|
const BlockTypeInfo* info = block_type_get_info(type);
|
|
if (info) {
|
|
strncpy(block->label, info->label, MAX_BLOCK_LABEL - 1);
|
|
|
|
// 创建输入槽位
|
|
for (int i = 0; i < info->input_count; i++) {
|
|
block_add_input(block,
|
|
i == 0 ? SLOT_STATEMENT : SLOT_VALUE,
|
|
info->input_types[i],
|
|
info->input_labels[i]);
|
|
}
|
|
|
|
// 创建输出槽位
|
|
for (int i = 0; i < info->output_count; i++) {
|
|
block_add_output(block,
|
|
info->output_types[i] == SLOT_VALUE_ANY ? SLOT_STATEMENT : SLOT_VALUE,
|
|
info->output_types[i],
|
|
info->output_labels[i]);
|
|
}
|
|
}
|
|
|
|
workspace_add_block(editor->workspace, block);
|
|
}
|
|
|
|
int block_editor_save(BlockEditor* editor, const char* filepath) {
|
|
return serializer_save(editor->workspace, filepath);
|
|
}
|
|
|
|
int block_editor_load(BlockEditor* editor, const char* filepath) {
|
|
return serializer_load(editor->workspace, filepath);
|
|
}
|
|
|
|
void block_editor_run(BlockEditor* editor) {
|
|
executor_start(editor->executor);
|
|
}
|
|
|
|
void block_editor_stop(BlockEditor* editor) {
|
|
executor_stop(editor->executor);
|
|
}
|
|
|
|
void block_editor_pause(BlockEditor* editor) {
|
|
executor_pause(editor->executor);
|
|
}
|