// ============================================================================ // block_editor.c - 编辑器主界面实现 // ============================================================================ #include "block_editor.h" #include "block_types.h" #include #include 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); }