feat: major engine overhaul - scene demo with lighting, sphere, ground
- Scene Demo: cube + sphere + ground plane with proper lighting - Audio: XAudio2 dynamic loading + WAV playback - Physics: expanded collision system - Renderer: improved pipeline with materials - UI: extended widget system - VisualScript: enhanced serializer + block interactions - ASM: optimized math/memory/profiling routines - Window: mouse input + scroll support
This commit is contained in:
1 parent
2653926d85
commit
0669d102ce
35 files changed
+1844
-314
No files matched your search
@@ -51,6 +51,7 @@ 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];
|
||||
@@ -76,6 +77,26 @@ static Block* next_from_output(Block* block, int output_index) {
|
||||
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);
|
||||
@@ -174,22 +195,54 @@ void executor_step(BlockExecutor* exec) {
|
||||
next = next_from_output(cur, cond ? 0 : 1);
|
||||
break;
|
||||
}
|
||||
case BLOCK_CONTROL_REPEAT: {
|
||||
case BLOCK_CONTROL_REPEAT:
|
||||
case BLOCK_CONTROL_WHILE: {
|
||||
int cond = get_input(cur, 1).as.boolean;
|
||||
if (cond) next = next_from_output(cur, 0);
|
||||
else next = next_from_output(cur, 0); // 退出循环: 走输出
|
||||
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;
|
||||
// 简化: 只执行一次,实际需要计数器
|
||||
log_info("循环 %.0f 次 (简化: 执行一次)", times);
|
||||
next = next_from_output(cur, 0);
|
||||
break;
|
||||
}
|
||||
case BLOCK_CONTROL_WHILE: {
|
||||
int cond = get_input(cur, 1).as.boolean;
|
||||
if (cond) next = next_from_output(cur, 0);
|
||||
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: {
|
||||
@@ -320,19 +373,32 @@ void executor_step(BlockExecutor* exec) {
|
||||
case BLOCK_FUNC_CALL: {
|
||||
const char* fname = get_input(cur, 1).as.string;
|
||||
log_info("调用函数 '%s'", fname);
|
||||
if (exec->call_stack_top < MAX_CALL_STACK) {
|
||||
|
||||
// 在工作区中查找同名函数定义积木
|
||||
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);
|
||||
}
|
||||
// TODO: 查找函数定义积木并跳转
|
||||
next = next_from_output(cur, 0);
|
||||
break;
|
||||
}
|
||||
case BLOCK_FUNC_RETURN: {
|
||||
if (exec->call_stack_top > 0) {
|
||||
exec->call_stack_top--;
|
||||
Block* caller = exec->call_stack[exec->call_stack_top].block;
|
||||
next = next_from_output(caller, 0);
|
||||
next = exec->call_stack[exec->call_stack_top].return_block;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -343,6 +409,14 @@ void executor_step(BlockExecutor* exec) {
|
||||
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("执行完成");
|
||||
|
||||
Reference in new issue
Block a user