// ============================================================================ // block_executor.c - 积木执行引擎 (完整实现) // ============================================================================ #include "block_executor.h" #include "block_types.h" #include #include #include #include #include // 日志回调 typedef void (*LogCallback)(const char* msg, int level); static LogCallback g_log_cb = NULL; static void log_info(const char* fmt, ...) { char buf[512]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (g_log_cb) g_log_cb(buf, 0); else printf("[INFO] %s\n", buf); } static void log_error(const char* fmt, ...) { char buf[512]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (g_log_cb) g_log_cb(buf, 2); else printf("[ERROR] %s\n", buf); } void executor_set_log_callback(LogCallback cb) { g_log_cb = cb; } // 值辅助 static SlotValue make_number(double v) { SlotValue v2; v2.type = SLOT_VALUE_NUMBER; v2.as.number = v; return v2; } static SlotValue make_string(const char* s) { SlotValue v; v.type = SLOT_VALUE_STRING; strncpy(v.as.string, s, 255); return v; } static SlotValue make_bool(int b) { SlotValue v; v.type = SLOT_VALUE_BOOLEAN; v.as.boolean = b; return v; } static SlotValue make_vec3(float x, float y, float z) { SlotValue v; v.type = SLOT_VALUE_VECTOR3; v.as.vector3.x = x; v.as.vector3.y = y; v.as.vector3.z = z; return v; } // 连接追踪:获取槽位的输入值(通过连线回溯) static SlotValue get_connected_value(BlockSlot* slot) { if (slot->connected) return slot->connected->value; return slot->value; } BlockExecutor* executor_create(BlockWorkspace* ws) { BlockExecutor* exec = (BlockExecutor*)calloc(1, sizeof(BlockExecutor)); if (!exec) return NULL; exec->workspace = ws; return exec; } void executor_destroy(BlockExecutor* exec) { free(exec); } void executor_start(BlockExecutor* exec) { exec->state = EXEC_RUNNING; exec->call_stack_top = 0; exec->loop_stack_top = 0; exec->current_block = NULL; for (int i = 0; i < exec->workspace->block_count; i++) { Block* block = exec->workspace->blocks[i]; if (block->type == BLOCK_EVENT_START) { exec->current_block = block; log_info("执行器启动: 找到 on_start 事件"); return; } } log_error("未找到 on_start 事件积木"); exec->state = EXEC_IDLE; } void executor_stop(BlockExecutor* exec) { exec->state = EXEC_IDLE; exec->current_block = NULL; } void executor_pause(BlockExecutor* exec) { if (exec->state == EXEC_RUNNING) exec->state = EXEC_PAUSED; } void executor_resume(BlockExecutor* exec) { if (exec->state == EXEC_PAUSED) exec->state = EXEC_RUNNING; } // 获取下一个执行的积木(通过输出端口连接) static Block* next_from_output(Block* block, int output_index) { if (output_index >= block->output_count) return NULL; BlockSlot* out = &block->outputs[output_index]; if (out->connected && out->connected->owner) return out->connected->owner; return NULL; } // 查找循环体链的最后一个积木(用于确定循环结束后应跳转到的积木) static Block* find_loop_body_end(Block* loop_block) { if (!loop_block || loop_block->output_count == 0 || !loop_block->outputs[0].connected) return NULL; Block* cur = loop_block->outputs[0].connected->owner; Block* prev = loop_block; int guard = 0; while (cur && guard < 1000) { guard++; if (cur == loop_block) return prev; // 回到循环头,则前一个为体尾 Block* next = NULL; if (cur->output_count > 0 && cur->outputs[0].connected) { next = cur->outputs[0].connected->owner; } if (!next) return cur; prev = cur; cur = next; } return cur; } // 获取值输入 static SlotValue get_input(Block* block, int idx) { if (idx >= block->input_count) return make_number(0); return get_connected_value(&block->inputs[idx]); } void executor_step(BlockExecutor* exec) { if (!exec->current_block) { exec->state = EXEC_IDLE; return; } Block* cur = exec->current_block; Block* next = NULL; switch (cur->type) { // === 事件 === case BLOCK_EVENT_START: case BLOCK_EVENT_UPDATE: case BLOCK_EVENT_COLLISION: case BLOCK_EVENT_MOUSE_CLICK: next = next_from_output(cur, 0); break; case BLOCK_EVENT_KEY_PRESSED: { const char* key = get_input(cur, 0).as.string; log_info("事件: 按键 '%s' (需要引擎集成)", key); next = next_from_output(cur, 0); break; } case BLOCK_EVENT_TIMER: { double interval = get_input(cur, 0).as.number; log_info("事件: 定时器 %.1fs (需要引擎集成)", interval); next = next_from_output(cur, 0); break; } // === 动作 === case BLOCK_ACTION_MOVE: { double x = get_input(cur, 1).as.number; double y = get_input(cur, 2).as.number; double z = get_input(cur, 3).as.number; log_info("移动物体: (%.2f, %.2f, %.2f)", x, y, z); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_ROTATE: { double x = get_input(cur, 1).as.number; double y = get_input(cur, 2).as.number; double z = get_input(cur, 3).as.number; log_info("旋转物体: (%.2f, %.2f, %.2f)", x, y, z); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_SCALE: { double x = get_input(cur, 1).as.number; double y = get_input(cur, 2).as.number; double z = get_input(cur, 3).as.number; log_info("缩放物体: (%.2f, %.2f, %.2f)", x, y, z); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_SET_POSITION: { double x = get_input(cur, 1).as.number; double y = get_input(cur, 2).as.number; double z = get_input(cur, 3).as.number; log_info("设置位置: (%.2f, %.2f, %.2f)", x, y, z); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_SET_ROTATION: { double x = get_input(cur, 1).as.number; double y = get_input(cur, 2).as.number; double z = get_input(cur, 3).as.number; log_info("设置旋转: (%.2f, %.2f, %.2f)", x, y, z); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_PLAY_SOUND: { const char* name = get_input(cur, 1).as.string; log_info("播放音效: '%s'", name); next = next_from_output(cur, 0); break; } case BLOCK_ACTION_DESTROY: log_info("销毁物体"); next = next_from_output(cur, 0); break; case BLOCK_ACTION_INSTANTIATE: { const char* prefab = get_input(cur, 1).as.string; log_info("实例化预制体: '%s'", prefab); next = next_from_output(cur, 0); break; } // === 控制流 === case BLOCK_CONTROL_IF: case BLOCK_CONTROL_IF_ELSE: { int cond = get_input(cur, 1).as.boolean; log_info("如果 %s", cond ? "真 -> Then" : "假 -> Else"); next = next_from_output(cur, cond ? 0 : 1); break; } case BLOCK_CONTROL_REPEAT: case BLOCK_CONTROL_WHILE: { int cond = get_input(cur, 1).as.boolean; LoopFrame* frame = NULL; if (exec->loop_stack_top > 0 && exec->loop_stack[exec->loop_stack_top - 1].loop_block == cur) { frame = &exec->loop_stack[exec->loop_stack_top - 1]; } else { if (exec->loop_stack_top < MAX_LOOP_STACK) { frame = &exec->loop_stack[exec->loop_stack_top++]; frame->loop_block = cur; frame->counter = 0; frame->target = 0; Block* body_end = find_loop_body_end(cur); frame->after_block = body_end ? next_from_output(body_end, 0) : NULL; } } if (frame && cond) { frame->counter++; next = next_from_output(cur, 0); } else { if (frame) exec->loop_stack_top--; next = frame ? frame->after_block : next_from_output(cur, 0); } break; } case BLOCK_CONTROL_REPEAT_TIMES: { double times = get_input(cur, 1).as.number; LoopFrame* frame = NULL; if (exec->loop_stack_top > 0 && exec->loop_stack[exec->loop_stack_top - 1].loop_block == cur) { frame = &exec->loop_stack[exec->loop_stack_top - 1]; frame->counter++; } else { if (exec->loop_stack_top < MAX_LOOP_STACK) { frame = &exec->loop_stack[exec->loop_stack_top++]; frame->loop_block = cur; frame->counter = 0; frame->target = (int)times; Block* body_end = find_loop_body_end(cur); frame->after_block = body_end ? next_from_output(body_end, 0) : NULL; } } if (frame && frame->counter < frame->target) { log_info("循环 %d / %d", frame->counter + 1, frame->target); next = next_from_output(cur, 0); } else { if (frame) exec->loop_stack_top--; next = frame ? frame->after_block : next_from_output(cur, 0); } break; } case BLOCK_CONTROL_WAIT: { double secs = get_input(cur, 1).as.number; log_info("等待 %.1f 秒", secs); exec->wait_timer = secs; exec->state = EXEC_WAITING; exec->current_block = next_from_output(cur, 0); return; } case BLOCK_CONTROL_FUNCTION_DEF: log_info("函数定义 (跳过)"); next = next_from_output(cur, 0); break; // === 运算 === case BLOCK_OP_ADD: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_number(a + b); log_info("%.1f + %.1f = %.1f", a, b, a + b); next = next_from_output(cur, 0); break; } case BLOCK_OP_SUB: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_number(a - b); next = next_from_output(cur, 0); break; } case BLOCK_OP_MUL: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_number(a * b); next = next_from_output(cur, 0); break; } case BLOCK_OP_DIV: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_number(b != 0 ? a / b : 0); next = next_from_output(cur, 0); break; } case BLOCK_OP_MOD: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_number(b != 0 ? fmod(a, b) : 0); next = next_from_output(cur, 0); break; } case BLOCK_OP_EQUALS: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_bool(a == b); next = next_from_output(cur, 0); break; } case BLOCK_OP_NOT_EQUALS: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_bool(a != b); next = next_from_output(cur, 0); break; } case BLOCK_OP_GREATER: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_bool(a > b); next = next_from_output(cur, 0); break; } case BLOCK_OP_LESS: { double a = get_input(cur, 0).as.number; double b = get_input(cur, 1).as.number; cur->outputs[0].value = make_bool(a < b); next = next_from_output(cur, 0); break; } case BLOCK_OP_AND: { int a = get_input(cur, 0).as.boolean; int b = get_input(cur, 1).as.boolean; cur->outputs[0].value = make_bool(a && b); next = next_from_output(cur, 0); break; } case BLOCK_OP_OR: { int a = get_input(cur, 0).as.boolean; int b = get_input(cur, 1).as.boolean; cur->outputs[0].value = make_bool(a || b); next = next_from_output(cur, 0); break; } case BLOCK_OP_NOT: { int a = get_input(cur, 0).as.boolean; cur->outputs[0].value = make_bool(!a); next = next_from_output(cur, 0); break; } // === 变量 === case BLOCK_VAR_GET: { const char* name = cur->label; SlotValue val = executor_get_variable(exec, name); cur->outputs[0].value = val; log_info("读取变量 '%s' = %.2f", name, val.as.number); next = next_from_output(cur, 0); break; } case BLOCK_VAR_SET: { const char* name = cur->label; SlotValue val = get_input(cur, 1); executor_set_variable(exec, name, val); log_info("设置变量 '%s' = %.2f", name, val.as.number); next = next_from_output(cur, 0); break; } case BLOCK_VAR_CREATE: { const char* name = cur->label; executor_create_variable(exec, name); log_info("创建变量 '%s' = 0", name); next = next_from_output(cur, 0); break; } // === 函数 === case BLOCK_FUNC_CALL: { const char* fname = get_input(cur, 1).as.string; log_info("调用函数 '%s'", fname); // 在工作区中查找同名函数定义积木 Block* def = NULL; for (int i = 0; i < exec->workspace->block_count; i++) { Block* b = exec->workspace->blocks[i]; if (b->type == BLOCK_CONTROL_FUNCTION_DEF && strcmp(b->label, fname) == 0) { def = b; break; } } if (def && exec->call_stack_top < MAX_CALL_STACK) { exec->call_stack[exec->call_stack_top].block = cur; exec->call_stack[exec->call_stack_top].return_block = next_from_output(cur, 0); exec->call_stack_top++; next = next_from_output(def, 0); } else { if (!def) log_error("未找到函数定义: '%s'", fname); next = next_from_output(cur, 0); } break; } case BLOCK_FUNC_RETURN: { if (exec->call_stack_top > 0) { exec->call_stack_top--; next = exec->call_stack[exec->call_stack_top].return_block; } break; } default: log_error("未知积木类型: %d", cur->type); next = next_from_output(cur, 0); break; } // 若当前 next 是某个活跃循环的 after_block,则跳转回循环头继续判断 if (next && exec->loop_stack_top > 0) { LoopFrame* frame = &exec->loop_stack[exec->loop_stack_top - 1]; if (next == frame->after_block) { next = frame->loop_block; } } exec->current_block = next; if (!exec->current_block) { log_info("执行完成"); exec->state = EXEC_IDLE; } } void executor_update(BlockExecutor* exec, double delta_time) { if (exec->state == EXEC_WAITING) { exec->wait_timer -= delta_time; if (exec->wait_timer <= 0) exec->state = EXEC_RUNNING; return; } if (exec->state != EXEC_RUNNING) return; int steps = 0; while (exec->current_block && exec->state == EXEC_RUNNING && steps < 1000) { executor_step(exec); steps++; } } void executor_set_variable(BlockExecutor* exec, const char* name, SlotValue value) { for (int i = 0; i < exec->variable_count; i++) { if (strcmp(exec->variables[i].name, name) == 0) { exec->variables[i].value = value; return; } } if (exec->variable_count < MAX_VARIABLES) { Variable* var = &exec->variables[exec->variable_count++]; strncpy(var->name, name, 63); var->value = value; var->used = 1; } } SlotValue executor_get_variable(BlockExecutor* exec, const char* name) { for (int i = 0; i < exec->variable_count; i++) { if (strcmp(exec->variables[i].name, name) == 0) return exec->variables[i].value; } return make_number(0); } void executor_create_variable(BlockExecutor* exec, const char* name) { executor_set_variable(exec, name, make_number(0)); }