核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
173 lines
5.2 KiB
C
173 lines
5.2 KiB
C
// ============================================================================
|
|
// block_workspace.c - 工作区管理实现
|
|
// ============================================================================
|
|
|
|
#include "block_workspace.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
BlockWorkspace* workspace_create(void) {
|
|
BlockWorkspace* ws = (BlockWorkspace*)calloc(1, sizeof(BlockWorkspace));
|
|
if (!ws) return NULL;
|
|
|
|
ws->zoom = 1.0f;
|
|
ws->next_block_id = 1;
|
|
|
|
return ws;
|
|
}
|
|
|
|
void workspace_destroy(BlockWorkspace* ws) {
|
|
if (!ws) return;
|
|
workspace_clear(ws);
|
|
free(ws);
|
|
}
|
|
|
|
int workspace_add_block(BlockWorkspace* ws, Block* block) {
|
|
if (ws->block_count >= MAX_WORKSPACE_BLOCKS) return -1;
|
|
if (!block) return -1;
|
|
|
|
block->id = ws->next_block_id++;
|
|
block->workspace = ws;
|
|
|
|
ws->blocks[ws->block_count++] = block;
|
|
return block->id;
|
|
}
|
|
|
|
void workspace_remove_block(BlockWorkspace* ws, int block_id) {
|
|
// 先移除所有相关连接
|
|
for (int i = ws->connection_count - 1; i >= 0; i--) {
|
|
BlockSlot* from = ws->connections[i].from;
|
|
BlockSlot* to = ws->connections[i].to;
|
|
if (from && from->owner && from->owner->id == block_id) {
|
|
workspace_remove_connection(ws, from);
|
|
} else if (to && to->owner && to->owner->id == block_id) {
|
|
workspace_remove_connection(ws, to);
|
|
}
|
|
}
|
|
|
|
// 移除积木
|
|
for (int i = 0; i < ws->block_count; i++) {
|
|
if (ws->blocks[i]->id == block_id) {
|
|
block_destroy(ws->blocks[i]);
|
|
ws->blocks[i] = ws->blocks[ws->block_count - 1];
|
|
ws->block_count--;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool workspace_add_connection(BlockWorkspace* ws, BlockSlot* from, BlockSlot* to) {
|
|
if (ws->connection_count >= MAX_WORKSPACE_CONNECTIONS) return false;
|
|
if (!from || !to) return false;
|
|
|
|
// 检查是否已连接
|
|
for (int i = 0; i < ws->connection_count; i++) {
|
|
if (ws->connections[i].from == from || ws->connections[i].to == to) {
|
|
return false; // 已有连接
|
|
}
|
|
}
|
|
|
|
// 建立连接
|
|
block_connect(from, to);
|
|
|
|
BlockConnection* conn = &ws->connections[ws->connection_count++];
|
|
conn->from = from;
|
|
conn->to = to;
|
|
|
|
return true;
|
|
}
|
|
|
|
void workspace_remove_connection(BlockWorkspace* ws, BlockSlot* slot) {
|
|
for (int i = ws->connection_count - 1; i >= 0; i--) {
|
|
if (ws->connections[i].from == slot || ws->connections[i].to == slot) {
|
|
block_disconnect(ws->connections[i].from);
|
|
ws->connections[i] = ws->connections[ws->connection_count - 1];
|
|
ws->connection_count--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void workspace_remove_all_connections(BlockWorkspace* ws, Block* block) {
|
|
if (!block) return;
|
|
|
|
for (int i = ws->connection_count - 1; i >= 0; i--) {
|
|
BlockSlot* from = ws->connections[i].from;
|
|
BlockSlot* to = ws->connections[i].to;
|
|
if ((from && from->owner == block) || (to && to->owner == block)) {
|
|
block_disconnect(from);
|
|
ws->connections[i] = ws->connections[ws->connection_count - 1];
|
|
ws->connection_count--;
|
|
}
|
|
}
|
|
}
|
|
|
|
Block* workspace_find_block(BlockWorkspace* ws, int block_id) {
|
|
for (int i = 0; i < ws->block_count; i++) {
|
|
if (ws->blocks[i]->id == block_id) return ws->blocks[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Block* workspace_find_block_at(BlockWorkspace* ws, float x, float y) {
|
|
// 从后往前找 (最后添加的在最上面)
|
|
for (int i = ws->block_count - 1; i >= 0; i--) {
|
|
if (block_contains_point(ws->blocks[i], x, y)) {
|
|
return ws->blocks[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BlockSlot* workspace_find_slot_at(BlockWorkspace* ws, float x, float y) {
|
|
float threshold = 10.0f;
|
|
|
|
for (int i = ws->block_count - 1; i >= 0; i--) {
|
|
Block* block = ws->blocks[i];
|
|
|
|
// 检查输出槽位
|
|
for (int j = 0; j < block->output_count; j++) {
|
|
BlockSlot* slot = &block->outputs[j];
|
|
float sx, sy;
|
|
block_slot_world_pos(slot, &sx, &sy);
|
|
float dx = x - sx;
|
|
float dy = y - sy;
|
|
if (dx * dx + dy * dy < threshold * threshold) {
|
|
return slot;
|
|
}
|
|
}
|
|
|
|
// 检查输入槽位
|
|
for (int j = 0; j < block->input_count; j++) {
|
|
BlockSlot* slot = &block->inputs[j];
|
|
float sx, sy;
|
|
block_slot_world_pos(slot, &sx, &sy);
|
|
float dx = x - sx;
|
|
float dy = y - sy;
|
|
if (dx * dx + dy * dy < threshold * threshold) {
|
|
return slot;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void workspace_screen_to_world(BlockWorkspace* ws, float sx, float sy, float* wx, float* wy) {
|
|
*wx = (sx / ws->zoom) + ws->view_x;
|
|
*wy = (sy / ws->zoom) + ws->view_y;
|
|
}
|
|
|
|
void workspace_world_to_screen(BlockWorkspace* ws, float wx, float wy, float* sx, float* sy) {
|
|
*sx = (wx - ws->view_x) * ws->zoom;
|
|
*sy = (wy - ws->view_y) * ws->zoom;
|
|
}
|
|
|
|
void workspace_clear(BlockWorkspace* ws) {
|
|
for (int i = 0; i < ws->block_count; i++) {
|
|
block_destroy(ws->blocks[i]);
|
|
}
|
|
ws->block_count = 0;
|
|
ws->connection_count = 0;
|
|
ws->selected_block = NULL;
|
|
}
|