- 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
152 lines
4.8 KiB
C
152 lines
4.8 KiB
C
// ============================================================================
|
|
// block_interaction.c - 交互系统实现
|
|
// ============================================================================
|
|
|
|
#include "block_interaction.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <Windows.h>
|
|
|
|
void interaction_init(BlockInteraction* inter) {
|
|
memset(inter, 0, sizeof(BlockInteraction));
|
|
}
|
|
|
|
void interaction_mouse_move(BlockInteraction* inter, BlockWorkspace* ws, int x, int y) {
|
|
inter->mouse_x = x;
|
|
inter->mouse_y = y;
|
|
|
|
// 拖拽积木
|
|
if (inter->dragging_block) {
|
|
float wx, wy;
|
|
workspace_screen_to_world(ws, (float)x, (float)y, &wx, &wy);
|
|
inter->dragging_block->x = wx - inter->drag_offset_x;
|
|
inter->dragging_block->y = wy - inter->drag_offset_y;
|
|
}
|
|
|
|
// 平移画布
|
|
if (inter->panning) {
|
|
float dx = (x - inter->pan_start_x) / ws->zoom;
|
|
float dy = (y - inter->pan_start_y) / ws->zoom;
|
|
ws->view_x = inter->view_start_x - dx;
|
|
ws->view_y = inter->view_start_y - dy;
|
|
}
|
|
}
|
|
|
|
void interaction_mouse_down(BlockInteraction* inter, BlockWorkspace* ws, int button) {
|
|
inter->mouse_down = 1;
|
|
inter->mouse_button = button;
|
|
|
|
float wx, wy;
|
|
workspace_screen_to_world(ws, (float)inter->mouse_x, (float)inter->mouse_y, &wx, &wy);
|
|
|
|
if (button == 0) { // 左键
|
|
// 检查是否点击槽位
|
|
BlockSlot* slot = workspace_find_slot_at(ws, wx, wy);
|
|
if (slot) {
|
|
// 开始连接
|
|
inter->connecting_from = slot;
|
|
inter->connect_start_x = wx;
|
|
inter->connect_start_y = wy;
|
|
return;
|
|
}
|
|
|
|
// 检查是否点击积木
|
|
Block* block = workspace_find_block_at(ws, wx, wy);
|
|
if (block) {
|
|
inter->dragging_block = block;
|
|
inter->drag_offset_x = wx - block->x;
|
|
inter->drag_offset_y = wy - block->y;
|
|
inter->selected_block = block;
|
|
ws->selected_block = block;
|
|
return;
|
|
}
|
|
|
|
// 点击空白区域: 取消选择
|
|
inter->selected_block = NULL;
|
|
ws->selected_block = NULL;
|
|
}
|
|
|
|
if (button == 1 || button == 2) { // 右键/中键: 平移
|
|
inter->panning = 1;
|
|
inter->pan_start_x = (float)inter->mouse_x;
|
|
inter->pan_start_y = (float)inter->mouse_y;
|
|
inter->view_start_x = ws->view_x;
|
|
inter->view_start_y = ws->view_y;
|
|
}
|
|
}
|
|
|
|
void interaction_mouse_up(BlockInteraction* inter, BlockWorkspace* ws, int button) {
|
|
inter->mouse_down = 0;
|
|
|
|
if (button == 0) {
|
|
// 结束拖拽积木
|
|
inter->dragging_block = NULL;
|
|
|
|
// 结束连接
|
|
if (inter->connecting_from) {
|
|
float wx, wy;
|
|
workspace_screen_to_world(ws, (float)inter->mouse_x, (float)inter->mouse_y, &wx, &wy);
|
|
|
|
BlockSlot* target = workspace_find_slot_at(ws, wx, wy);
|
|
if (target && target != inter->connecting_from) {
|
|
// 尝试建立连接
|
|
workspace_add_connection(ws, inter->connecting_from, target);
|
|
}
|
|
inter->connecting_from = NULL;
|
|
}
|
|
}
|
|
|
|
if (button == 1 || button == 2) {
|
|
inter->panning = 0;
|
|
}
|
|
}
|
|
|
|
void interaction_key_down(BlockInteraction* inter, BlockWorkspace* ws, int key) {
|
|
inter->key = key;
|
|
inter->key_pressed = 1;
|
|
|
|
// 删除选中的积木
|
|
if (key == 46 || key == 8) { // DELETE 或 BACKSPACE
|
|
if (inter->selected_block) {
|
|
workspace_remove_block(ws, inter->selected_block->id);
|
|
inter->selected_block = NULL;
|
|
ws->selected_block = NULL;
|
|
}
|
|
}
|
|
|
|
// 复制/粘贴 (Ctrl+C / Ctrl+V)
|
|
static Block* clipboard = NULL;
|
|
if (key == 'C' && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
|
|
if (inter->selected_block) {
|
|
if (clipboard) block_destroy(clipboard);
|
|
clipboard = block_copy(inter->selected_block);
|
|
}
|
|
}
|
|
if (key == 'V' && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
|
|
if (clipboard) {
|
|
Block* copy = block_copy(clipboard);
|
|
if (copy) {
|
|
copy->x += 20.0f;
|
|
copy->y += 20.0f;
|
|
copy->id = ws->next_block_id++;
|
|
workspace_add_block(ws, copy);
|
|
inter->selected_block = copy;
|
|
ws->selected_block = copy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void interaction_mouse_wheel(BlockInteraction* inter, BlockWorkspace* ws, int delta) {
|
|
float zoom_factor = delta > 0 ? 1.1f : 0.9f;
|
|
ws->zoom *= zoom_factor;
|
|
if (ws->zoom < 0.25f) ws->zoom = 0.25f;
|
|
if (ws->zoom > 4.0f) ws->zoom = 4.0f;
|
|
}
|
|
|
|
void interaction_update(BlockInteraction* inter, BlockWorkspace* ws) {
|
|
inter->key_pressed = 0;
|
|
(void)ws;
|
|
}
|