Files
lity3d/Engine/VisualScript/block_executor.c
T
shuiyu1123 2d56cb3bc9 MiMoEngine ASM: x86-64 MASM汇编+C混合架构游戏引擎
核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2)
外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言
含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
2026-07-10 19:20:40 +08:00

192 lines
5.4 KiB
C

// ============================================================================
// block_executor.c - 积木执行引擎实现
// ============================================================================
#include "block_executor.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
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->current_block = NULL;
// 找到 on_start 事件积木
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;
break;
}
}
}
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;
}
}
void executor_step(BlockExecutor* exec) {
if (!exec->current_block) return;
// 执行当前积木
Block* current = exec->current_block;
Block* next = NULL;
switch (current->type) {
case BLOCK_EVENT_START:
case BLOCK_EVENT_UPDATE:
// 执行语句输出连接的积木
if (current->output_count > 0) {
BlockSlot* out = &current->outputs[0];
if (out->connected && out->connected->owner) {
next = out->connected->owner;
}
}
break;
case BLOCK_ACTION_MOVE:
// 获取参数
if (current->input_count >= 4) {
SlotValue x = block_slot_get_value(&current->inputs[1]);
SlotValue y = block_slot_get_value(&current->inputs[2]);
SlotValue z = block_slot_get_value(&current->inputs[3]);
// TODO: 实际移动物体
}
next = current->next;
break;
case BLOCK_CONTROL_IF:
if (current->input_count >= 2) {
SlotValue cond = block_slot_get_value(&current->inputs[1]);
if (cond.as.boolean) {
// 执行 Then 分支
if (current->output_count > 0) {
BlockSlot* out = &current->outputs[0];
if (out->connected && out->connected->owner) {
next = out->connected->owner;
}
}
} else {
// 执行 Else 分支
if (current->output_count > 1) {
BlockSlot* out = &current->outputs[1];
if (out->connected && out->connected->owner) {
next = out->connected->owner;
}
}
}
}
break;
case BLOCK_OP_ADD:
if (current->input_count >= 2) {
SlotValue a = block_slot_get_value(&current->inputs[0]);
SlotValue b = block_slot_get_value(&current->inputs[1]);
SlotValue result;
result.type = SLOT_VALUE_NUMBER;
result.as.number = a.as.number + b.as.number;
if (current->output_count > 0) {
current->outputs[0].value = result;
}
}
break;
case BLOCK_VAR_SET:
if (current->input_count >= 2) {
SlotValue val = block_slot_get_value(&current->inputs[1]);
// TODO: 获取变量名
}
next = current->next;
break;
default:
next = current->next;
break;
}
exec->current_block = next;
if (!exec->current_block) {
exec->state = EXEC_IDLE;
}
}
void executor_update(BlockExecutor* exec, double delta_time) {
if (exec->state != EXEC_RUNNING) return;
// 处理等待
if (exec->state == EXEC_WAITING) {
exec->wait_timer -= delta_time;
if (exec->wait_timer <= 0) {
exec->state = EXEC_RUNNING;
}
return;
}
// 执行多步以避免卡顿
int steps = 0;
while (exec->current_block && steps < 100) {
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;
}
}
SlotValue empty = {0};
return empty;
}
void executor_create_variable(BlockExecutor* exec, const char* name) {
SlotValue val = {0};
val.type = SLOT_VALUE_NUMBER;
val.as.number = 0;
executor_set_variable(exec, name, val);
}