核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
192 lines
5.4 KiB
C
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 = ¤t->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(¤t->inputs[1]);
|
|
SlotValue y = block_slot_get_value(¤t->inputs[2]);
|
|
SlotValue z = block_slot_get_value(¤t->inputs[3]);
|
|
// TODO: 实际移动物体
|
|
}
|
|
next = current->next;
|
|
break;
|
|
|
|
case BLOCK_CONTROL_IF:
|
|
if (current->input_count >= 2) {
|
|
SlotValue cond = block_slot_get_value(¤t->inputs[1]);
|
|
if (cond.as.boolean) {
|
|
// 执行 Then 分支
|
|
if (current->output_count > 0) {
|
|
BlockSlot* out = ¤t->outputs[0];
|
|
if (out->connected && out->connected->owner) {
|
|
next = out->connected->owner;
|
|
}
|
|
}
|
|
} else {
|
|
// 执行 Else 分支
|
|
if (current->output_count > 1) {
|
|
BlockSlot* out = ¤t->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(¤t->inputs[0]);
|
|
SlotValue b = block_slot_get_value(¤t->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(¤t->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);
|
|
}
|