Feature/physics and tilemap enhancement (#247)
* feat(behavior-tree,tilemap): 修复编辑器连线缩放问题并增强插件系统 * feat(node-editor,blueprint): 新增通用节点编辑器和蓝图可视化脚本系统 * feat(editor,tilemap): 优化编辑器UI样式和Tilemap编辑器功能 * fix: 修复CodeQL安全警告和CI类型检查错误 * fix: 修复CodeQL安全警告和CI类型检查错误 * fix: 修复CodeQL安全警告和CI类型检查错误
This commit is contained in:
262
packages/node-editor/src/styles/Canvas.css
Normal file
262
packages/node-editor/src/styles/Canvas.css
Normal file
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* Canvas Styles
|
||||
* 画布样式
|
||||
*/
|
||||
|
||||
/* ==================== Canvas Container 画布容器 ==================== */
|
||||
.ne-canvas {
|
||||
background: var(--ne-canvas-bg);
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.ne-canvas:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* ==================== Canvas Content 画布内容 ==================== */
|
||||
.ne-canvas-content {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* ==================== Canvas Grid 画布网格 ==================== */
|
||||
.ne-canvas-grid {
|
||||
z-index: var(--ne-z-grid);
|
||||
}
|
||||
|
||||
/* ==================== Selection Box 选择框 ==================== */
|
||||
.ne-selection-box {
|
||||
position: absolute;
|
||||
border: 1px dashed var(--ne-node-border-selected);
|
||||
background: rgba(0, 120, 212, 0.1);
|
||||
pointer-events: none;
|
||||
z-index: var(--ne-z-dragging);
|
||||
}
|
||||
|
||||
/* ==================== Minimap 小地图 ==================== */
|
||||
.ne-minimap {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid var(--ne-node-border);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
z-index: var(--ne-z-menu);
|
||||
}
|
||||
|
||||
.ne-minimap-viewport {
|
||||
position: absolute;
|
||||
border: 2px solid var(--ne-node-border-selected);
|
||||
background: rgba(0, 120, 212, 0.2);
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.ne-minimap-node {
|
||||
position: absolute;
|
||||
background: var(--ne-node-bg);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* ==================== Zoom Controls 缩放控制 ==================== */
|
||||
.ne-zoom-controls {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
z-index: var(--ne-z-menu);
|
||||
}
|
||||
|
||||
.ne-zoom-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
border: 1px solid var(--ne-node-border);
|
||||
background: var(--ne-node-bg);
|
||||
color: var(--ne-text-primary);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
transition: background var(--ne-transition-fast),
|
||||
border-color var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-zoom-btn:hover {
|
||||
background: var(--ne-node-bg-hover);
|
||||
border-color: var(--ne-node-border-selected);
|
||||
}
|
||||
|
||||
.ne-zoom-btn:active {
|
||||
background: var(--ne-node-bg-selected);
|
||||
}
|
||||
|
||||
.ne-zoom-level {
|
||||
padding: 4px 8px;
|
||||
font-size: var(--ne-font-size-small);
|
||||
color: var(--ne-text-secondary);
|
||||
text-align: center;
|
||||
background: var(--ne-node-bg);
|
||||
border: 1px solid var(--ne-node-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* ==================== Context Menu 右键菜单 ==================== */
|
||||
.ne-context-menu {
|
||||
position: fixed;
|
||||
min-width: 180px;
|
||||
background: var(--ne-node-bg);
|
||||
border: 1px solid var(--ne-node-border);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||
padding: 4px 0;
|
||||
z-index: var(--ne-z-menu);
|
||||
font-family: var(--ne-font-family);
|
||||
font-size: var(--ne-font-size-body);
|
||||
}
|
||||
|
||||
.ne-context-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
color: var(--ne-text-primary);
|
||||
cursor: pointer;
|
||||
transition: background var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-context-menu-item:hover {
|
||||
background: var(--ne-node-bg-hover);
|
||||
}
|
||||
|
||||
.ne-context-menu-item.disabled {
|
||||
color: var(--ne-text-muted);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.ne-context-menu-item.disabled:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-label {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-shortcut {
|
||||
color: var(--ne-text-muted);
|
||||
font-size: var(--ne-font-size-small);
|
||||
}
|
||||
|
||||
.ne-context-menu-separator {
|
||||
height: 1px;
|
||||
background: var(--ne-node-border);
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.ne-context-menu-submenu {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ne-context-menu-submenu::after {
|
||||
content: '▶';
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
font-size: 10px;
|
||||
color: var(--ne-text-muted);
|
||||
}
|
||||
|
||||
/* ==================== Search Popup 搜索弹窗 ==================== */
|
||||
.ne-search-popup {
|
||||
position: fixed;
|
||||
width: 300px;
|
||||
max-height: 400px;
|
||||
background: var(--ne-node-bg);
|
||||
border: 1px solid var(--ne-node-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
z-index: var(--ne-z-menu);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ne-search-input {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--ne-node-border);
|
||||
background: transparent;
|
||||
color: var(--ne-text-primary);
|
||||
font-size: var(--ne-font-size-title);
|
||||
font-family: var(--ne-font-family);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ne-search-input::placeholder {
|
||||
color: var(--ne-text-muted);
|
||||
}
|
||||
|
||||
.ne-search-results {
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ne-search-category {
|
||||
padding: 8px 16px 4px;
|
||||
color: var(--ne-text-muted);
|
||||
font-size: var(--ne-font-size-small);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.ne-search-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
transition: background var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-search-result:hover,
|
||||
.ne-search-result.selected {
|
||||
background: var(--ne-node-bg-hover);
|
||||
}
|
||||
|
||||
.ne-search-result-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ne-search-result-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ne-search-result-name {
|
||||
color: var(--ne-text-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ne-search-result-path {
|
||||
color: var(--ne-text-muted);
|
||||
font-size: var(--ne-font-size-small);
|
||||
}
|
||||
|
||||
.ne-search-empty {
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
color: var(--ne-text-muted);
|
||||
}
|
||||
179
packages/node-editor/src/styles/Connection.css
Normal file
179
packages/node-editor/src/styles/Connection.css
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Connection Line Styles
|
||||
* 连接线样式
|
||||
*/
|
||||
|
||||
/* ==================== Connection Layer 连接层 ==================== */
|
||||
.ne-connection-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: var(--ne-z-connections);
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* ==================== Connection Path 连接路径 ==================== */
|
||||
.ne-connection {
|
||||
fill: none;
|
||||
stroke-width: var(--ne-connection-width);
|
||||
stroke-linecap: round;
|
||||
pointer-events: stroke;
|
||||
cursor: pointer;
|
||||
transition: stroke-width var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-connection:hover {
|
||||
stroke-width: var(--ne-connection-width-hover);
|
||||
}
|
||||
|
||||
.ne-connection.selected {
|
||||
stroke: var(--ne-connection-selected);
|
||||
stroke-width: var(--ne-connection-width-hover);
|
||||
filter: drop-shadow(0 0 4px var(--ne-connection-selected));
|
||||
}
|
||||
|
||||
/* ==================== Connection Type Colors 连接类型颜色 ==================== */
|
||||
.ne-connection.exec {
|
||||
stroke: var(--ne-pin-exec);
|
||||
stroke-width: var(--ne-connection-width-exec);
|
||||
}
|
||||
|
||||
.ne-connection.bool { stroke: var(--ne-pin-bool); }
|
||||
.ne-connection.int { stroke: var(--ne-pin-int); }
|
||||
.ne-connection.float { stroke: var(--ne-pin-float); }
|
||||
.ne-connection.string { stroke: var(--ne-pin-string); }
|
||||
.ne-connection.vector2 { stroke: var(--ne-pin-vector2); }
|
||||
.ne-connection.vector3 { stroke: var(--ne-pin-vector3); }
|
||||
.ne-connection.vector4 { stroke: var(--ne-pin-vector4); }
|
||||
.ne-connection.color { stroke: var(--ne-pin-color); }
|
||||
.ne-connection.object { stroke: var(--ne-pin-object); }
|
||||
.ne-connection.array { stroke: var(--ne-pin-array); }
|
||||
.ne-connection.map { stroke: var(--ne-pin-map); }
|
||||
.ne-connection.struct { stroke: var(--ne-pin-struct); }
|
||||
.ne-connection.enum { stroke: var(--ne-pin-enum); }
|
||||
.ne-connection.delegate { stroke: var(--ne-pin-delegate); }
|
||||
.ne-connection.any { stroke: var(--ne-pin-any); }
|
||||
|
||||
/* ==================== Connection Preview 连接预览 ==================== */
|
||||
.ne-connection-preview {
|
||||
fill: none;
|
||||
stroke: var(--ne-connection-preview);
|
||||
stroke-width: 3px;
|
||||
stroke-dasharray: 8 4;
|
||||
pointer-events: none;
|
||||
animation: ne-connection-dash 0.3s linear infinite;
|
||||
filter: drop-shadow(0 0 4px currentColor);
|
||||
}
|
||||
|
||||
.ne-connection-preview.valid {
|
||||
stroke: var(--ne-state-success);
|
||||
stroke-dasharray: none;
|
||||
stroke-width: 3px;
|
||||
filter: drop-shadow(0 0 8px var(--ne-state-success));
|
||||
}
|
||||
|
||||
.ne-connection-preview.invalid {
|
||||
stroke: var(--ne-connection-invalid);
|
||||
filter: drop-shadow(0 0 6px var(--ne-connection-invalid));
|
||||
}
|
||||
|
||||
/* Preview type colors */
|
||||
.ne-connection-preview.exec { stroke: var(--ne-pin-exec); }
|
||||
.ne-connection-preview.bool { stroke: var(--ne-pin-bool); }
|
||||
.ne-connection-preview.int { stroke: var(--ne-pin-int); }
|
||||
.ne-connection-preview.float { stroke: var(--ne-pin-float); }
|
||||
.ne-connection-preview.string { stroke: var(--ne-pin-string); }
|
||||
.ne-connection-preview.vector2 { stroke: var(--ne-pin-vector2); }
|
||||
.ne-connection-preview.vector3 { stroke: var(--ne-pin-vector3); }
|
||||
.ne-connection-preview.vector4 { stroke: var(--ne-pin-vector4); }
|
||||
.ne-connection-preview.color { stroke: var(--ne-pin-color); }
|
||||
.ne-connection-preview.object { stroke: var(--ne-pin-object); }
|
||||
.ne-connection-preview.array { stroke: var(--ne-pin-array); }
|
||||
.ne-connection-preview.map { stroke: var(--ne-pin-map); }
|
||||
.ne-connection-preview.struct { stroke: var(--ne-pin-struct); }
|
||||
.ne-connection-preview.enum { stroke: var(--ne-pin-enum); }
|
||||
.ne-connection-preview.delegate { stroke: var(--ne-pin-delegate); }
|
||||
.ne-connection-preview.any { stroke: var(--ne-pin-any); }
|
||||
|
||||
@keyframes ne-connection-dash {
|
||||
to {
|
||||
stroke-dashoffset: -12;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Connection Hit Area 连接点击区域 ==================== */
|
||||
.ne-connection-hit {
|
||||
fill: none;
|
||||
stroke: transparent;
|
||||
stroke-width: 20px;
|
||||
pointer-events: stroke;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ne-connection-hit:hover + .ne-connection-glow + .ne-connection {
|
||||
stroke-width: var(--ne-connection-width-hover);
|
||||
}
|
||||
|
||||
/* ==================== Connection Glow 连接发光 ==================== */
|
||||
.ne-connection-glow {
|
||||
fill: none;
|
||||
stroke-width: 8px;
|
||||
opacity: 0;
|
||||
filter: blur(4px);
|
||||
pointer-events: none;
|
||||
transition: opacity var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-connection-glow.exec { stroke: var(--ne-pin-exec); }
|
||||
.ne-connection-glow.bool { stroke: var(--ne-pin-bool); }
|
||||
.ne-connection-glow.int { stroke: var(--ne-pin-int); }
|
||||
.ne-connection-glow.float { stroke: var(--ne-pin-float); }
|
||||
.ne-connection-glow.string { stroke: var(--ne-pin-string); }
|
||||
.ne-connection-glow.vector2 { stroke: var(--ne-pin-vector2); }
|
||||
.ne-connection-glow.vector3 { stroke: var(--ne-pin-vector3); }
|
||||
.ne-connection-glow.vector4 { stroke: var(--ne-pin-vector4); }
|
||||
.ne-connection-glow.color { stroke: var(--ne-pin-color); }
|
||||
.ne-connection-glow.object { stroke: var(--ne-pin-object); }
|
||||
.ne-connection-glow.array { stroke: var(--ne-pin-array); }
|
||||
.ne-connection-glow.map { stroke: var(--ne-pin-map); }
|
||||
.ne-connection-glow.struct { stroke: var(--ne-pin-struct); }
|
||||
.ne-connection-glow.enum { stroke: var(--ne-pin-enum); }
|
||||
.ne-connection-glow.delegate { stroke: var(--ne-pin-delegate); }
|
||||
.ne-connection-glow.any { stroke: var(--ne-pin-any); }
|
||||
|
||||
.ne-connection-hit:hover + .ne-connection-glow {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* ==================== Connection Flow Animation 连接流动动画 ==================== */
|
||||
.ne-connection.exec.animated {
|
||||
stroke-dasharray: 4 8;
|
||||
animation: ne-exec-flow 0.4s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes ne-exec-flow {
|
||||
to {
|
||||
stroke-dashoffset: -12;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Reroute Node 重路由节点 ==================== */
|
||||
.ne-reroute {
|
||||
fill: var(--ne-node-bg);
|
||||
stroke: currentColor;
|
||||
stroke-width: 2px;
|
||||
cursor: move;
|
||||
transition: transform var(--ne-transition-fast);
|
||||
}
|
||||
|
||||
.ne-reroute:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.ne-reroute.selected {
|
||||
stroke: var(--ne-connection-selected);
|
||||
filter: drop-shadow(0 0 4px var(--ne-connection-selected));
|
||||
}
|
||||
290
packages/node-editor/src/styles/ContextMenu.css
Normal file
290
packages/node-editor/src/styles/ContextMenu.css
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* Context Menu Styles
|
||||
* 上下文菜单样式
|
||||
*/
|
||||
|
||||
/* ==================== Menu Container 菜单容器 ==================== */
|
||||
.ne-context-menu {
|
||||
position: fixed;
|
||||
z-index: var(--ne-z-menu);
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
max-height: 500px;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
|
||||
font-family: var(--ne-font-family);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* ==================== Menu Header 菜单头部 ==================== */
|
||||
.ne-context-menu-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 10px;
|
||||
background: #252525;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.ne-context-menu-title {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
.ne-context-menu-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.ne-context-menu-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 11px;
|
||||
color: #909090;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ne-context-menu-checkbox input {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==================== Search Box 搜索框 ==================== */
|
||||
.ne-context-menu-search {
|
||||
padding: 6px 8px;
|
||||
border-bottom: 1px solid #303030;
|
||||
background: #1e1e1e;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-input {
|
||||
width: 100%;
|
||||
padding: 6px 28px 6px 8px;
|
||||
font-size: 12px;
|
||||
font-family: var(--ne-font-family);
|
||||
background: #0a0a0a;
|
||||
border: 1px solid #404040;
|
||||
border-radius: 2px;
|
||||
color: #e0e0e0;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-input::placeholder {
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-input:focus {
|
||||
border-color: #5080c0;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-clear {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #606060;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ne-context-menu-search-clear:hover {
|
||||
color: #a0a0a0;
|
||||
}
|
||||
|
||||
/* ==================== Content Area 内容区域 ==================== */
|
||||
.ne-context-menu-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.ne-context-menu-content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.ne-context-menu-content::-webkit-scrollbar-track {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.ne-context-menu-content::-webkit-scrollbar-thumb {
|
||||
background: #404040;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ne-context-menu-content::-webkit-scrollbar-thumb:hover {
|
||||
background: #505050;
|
||||
}
|
||||
|
||||
/* ==================== Category Section 分类区域 ==================== */
|
||||
.ne-context-menu-category {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ne-context-menu-category-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 8px;
|
||||
font-size: 11px;
|
||||
color: #808080;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ne-context-menu-category-header:hover {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.ne-context-menu-category-chevron {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 8px;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.ne-context-menu-category.expanded .ne-context-menu-category-chevron {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.ne-context-menu-category-title {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ne-context-menu-category-items {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ne-context-menu-category.expanded .ne-context-menu-category-items {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ==================== Menu Item 菜单项 ==================== */
|
||||
.ne-context-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 4px 8px 4px 24px;
|
||||
cursor: pointer;
|
||||
transition: background 0.1s ease;
|
||||
}
|
||||
|
||||
.ne-context-menu-item:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.ne-context-menu-item.highlighted {
|
||||
background: #264f78;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-icon-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-icon-dot.event { background: var(--ne-category-event); }
|
||||
.ne-context-menu-item-icon-dot.function { background: var(--ne-category-function); }
|
||||
.ne-context-menu-item-icon-dot.pure { background: var(--ne-category-pure); }
|
||||
.ne-context-menu-item-icon-dot.flow { background: var(--ne-category-flow); }
|
||||
.ne-context-menu-item-icon-dot.variable { background: var(--ne-category-variable); }
|
||||
.ne-context-menu-item-icon-dot.literal { background: var(--ne-category-literal); }
|
||||
.ne-context-menu-item-icon-dot.comment { background: var(--ne-category-comment); }
|
||||
.ne-context-menu-item-icon-dot.custom { background: var(--ne-category-custom); }
|
||||
|
||||
/* Function icon - f */
|
||||
.ne-context-menu-item-icon-func {
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
color: var(--ne-category-function);
|
||||
}
|
||||
|
||||
.ne-context-menu-item-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-title {
|
||||
font-size: 12px;
|
||||
color: #d0d0d0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-title .highlight {
|
||||
background: #4a6a2a;
|
||||
color: #90ff90;
|
||||
padding: 0 1px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.ne-context-menu-item-description {
|
||||
font-size: 10px;
|
||||
color: #707070;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
/* ==================== Empty State 空状态 ==================== */
|
||||
.ne-context-menu-empty {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #606060;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* ==================== Footer 底部 ==================== */
|
||||
.ne-context-menu-footer {
|
||||
padding: 6px 10px;
|
||||
border-top: 1px solid #303030;
|
||||
background: #1e1e1e;
|
||||
font-size: 10px;
|
||||
color: #606060;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ne-context-menu-footer kbd {
|
||||
display: inline-block;
|
||||
padding: 1px 4px;
|
||||
font-family: var(--ne-font-family-mono);
|
||||
font-size: 9px;
|
||||
background: #303030;
|
||||
border-radius: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
191
packages/node-editor/src/styles/Dialog.css
Normal file
191
packages/node-editor/src/styles/Dialog.css
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Dialog Styles
|
||||
* 对话框样式
|
||||
*/
|
||||
|
||||
/* ==================== Overlay 遮罩层 ==================== */
|
||||
.ne-dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(2px);
|
||||
z-index: var(--ne-z-dialog);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: ne-dialog-fade-in 0.15s ease;
|
||||
}
|
||||
|
||||
@keyframes ne-dialog-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Dialog Container 对话框容器 ==================== */
|
||||
.ne-dialog {
|
||||
min-width: 320px;
|
||||
max-width: 450px;
|
||||
background: #1e1e1e;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
font-family: var(--ne-font-family);
|
||||
animation: ne-dialog-slide-in 0.15s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@keyframes ne-dialog-slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95) translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Dialog Header 对话框头部 ==================== */
|
||||
.ne-dialog-header {
|
||||
padding: 12px 16px;
|
||||
background: #252525;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.ne-dialog-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* Type-specific header colors */
|
||||
.ne-dialog-danger .ne-dialog-header {
|
||||
background: linear-gradient(90deg, #4a1a1a 0%, #252525 100%);
|
||||
}
|
||||
|
||||
.ne-dialog-warning .ne-dialog-header {
|
||||
background: linear-gradient(90deg, #4a3a1a 0%, #252525 100%);
|
||||
}
|
||||
|
||||
.ne-dialog-info .ne-dialog-header {
|
||||
background: linear-gradient(90deg, #1a3a4a 0%, #252525 100%);
|
||||
}
|
||||
|
||||
/* ==================== Dialog Body 对话框主体 ==================== */
|
||||
.ne-dialog-body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ne-dialog-message {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: #b0b0b0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ==================== Dialog Footer 对话框底部 ==================== */
|
||||
.ne-dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
background: #1a1a1a;
|
||||
border-top: 1px solid #303030;
|
||||
}
|
||||
|
||||
/* ==================== Dialog Buttons 对话框按钮 ==================== */
|
||||
.ne-dialog-btn {
|
||||
padding: 6px 16px;
|
||||
font-size: 12px;
|
||||
font-family: var(--ne-font-family);
|
||||
font-weight: 500;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.ne-dialog-btn:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-cancel {
|
||||
background: #2a2a2a;
|
||||
border-color: #404040;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-cancel:hover {
|
||||
background: #353535;
|
||||
border-color: #505050;
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-cancel:active {
|
||||
background: #252525;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-confirm {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-danger {
|
||||
background: #8b2a2a;
|
||||
border-color: #a03030;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-danger:hover {
|
||||
background: #9b3535;
|
||||
border-color: #b04040;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-danger:active {
|
||||
background: #7b2525;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-danger:focus {
|
||||
box-shadow: 0 0 0 2px rgba(160, 48, 48, 0.4);
|
||||
}
|
||||
|
||||
.ne-dialog-btn-warning {
|
||||
background: #8b6a2a;
|
||||
border-color: #a08030;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-warning:hover {
|
||||
background: #9b7535;
|
||||
border-color: #b09040;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-warning:active {
|
||||
background: #7b5a25;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-warning:focus {
|
||||
box-shadow: 0 0 0 2px rgba(160, 128, 48, 0.4);
|
||||
}
|
||||
|
||||
.ne-dialog-btn-info {
|
||||
background: #2a5a8b;
|
||||
border-color: #3070a0;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-info:hover {
|
||||
background: #356a9b;
|
||||
border-color: #4080b0;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-info:active {
|
||||
background: #254a7b;
|
||||
}
|
||||
|
||||
.ne-dialog-btn-info:focus {
|
||||
box-shadow: 0 0 0 2px rgba(48, 112, 160, 0.4);
|
||||
}
|
||||
265
packages/node-editor/src/styles/GraphNode.css
Normal file
265
packages/node-editor/src/styles/GraphNode.css
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Graph Node Styles
|
||||
* 图节点样式
|
||||
*/
|
||||
|
||||
/* ==================== Node Container 节点容器 ==================== */
|
||||
.ne-node {
|
||||
position: absolute;
|
||||
min-width: var(--ne-node-min-width);
|
||||
max-width: var(--ne-node-max-width);
|
||||
background: var(--ne-node-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--ne-node-border);
|
||||
border-radius: var(--ne-node-border-radius);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
font-family: var(--ne-font-family);
|
||||
user-select: none;
|
||||
cursor: grab;
|
||||
transition: box-shadow var(--ne-transition-normal),
|
||||
border-color var(--ne-transition-normal);
|
||||
}
|
||||
|
||||
.ne-node:hover {
|
||||
border-color: rgba(80, 80, 100, 0.6);
|
||||
}
|
||||
|
||||
.ne-node.selected {
|
||||
border-color: var(--ne-node-border-selected);
|
||||
box-shadow: 0 0 0 1px var(--ne-node-border-selected),
|
||||
0 0 16px rgba(229, 160, 32, 0.4),
|
||||
0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.ne-node.dragging {
|
||||
cursor: grabbing;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
|
||||
z-index: var(--ne-z-dragging);
|
||||
}
|
||||
|
||||
/* ==================== Node Header 节点头部 ==================== */
|
||||
.ne-node-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 10px;
|
||||
min-height: var(--ne-node-header-height);
|
||||
border-radius: calc(var(--ne-node-border-radius) - 1px) calc(var(--ne-node-border-radius) - 1px) 0 0;
|
||||
color: var(--ne-text-title);
|
||||
font-size: var(--ne-font-size-title);
|
||||
font-weight: 500;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Gradient overlay for header */
|
||||
.ne-node-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0.15;
|
||||
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Node category header colors */
|
||||
.ne-node-header.event {
|
||||
background: linear-gradient(90deg, var(--ne-category-event) 0%, var(--ne-category-event-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.function {
|
||||
background: linear-gradient(90deg, var(--ne-category-function) 0%, var(--ne-category-function-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.pure {
|
||||
background: linear-gradient(90deg, var(--ne-category-pure) 0%, var(--ne-category-pure-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.flow {
|
||||
background: linear-gradient(90deg, var(--ne-category-flow) 0%, var(--ne-category-flow-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.variable {
|
||||
background: linear-gradient(90deg, var(--ne-category-variable) 0%, var(--ne-category-variable-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.literal {
|
||||
background: linear-gradient(90deg, var(--ne-category-literal) 0%, var(--ne-category-literal-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.comment {
|
||||
background: linear-gradient(90deg, var(--ne-category-comment) 0%, var(--ne-category-comment-dark) 100%);
|
||||
}
|
||||
|
||||
.ne-node-header.custom {
|
||||
background: linear-gradient(90deg, var(--ne-category-custom) 0%, var(--ne-category-custom-dark) 100%);
|
||||
}
|
||||
|
||||
/* Header icon - diamond shape for events */
|
||||
.ne-node-header-icon {
|
||||
flex-shrink: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ne-node-header.event .ne-node-header-icon::before {
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #fff;
|
||||
transform: rotate(45deg);
|
||||
border-radius: 1px;
|
||||
box-shadow: 0 0 4px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.ne-node-header-title {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.ne-node-header-subtitle {
|
||||
font-size: var(--ne-font-size-small);
|
||||
font-weight: 400;
|
||||
opacity: 0.7;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* Header exec pin */
|
||||
.ne-node-header-exec {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: transparent;
|
||||
border: 2px solid #a04040;
|
||||
cursor: pointer;
|
||||
transition: all var(--ne-transition-fast);
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ne-node-header-exec:hover {
|
||||
border-color: #ff6060;
|
||||
box-shadow: 0 0 6px rgba(255, 96, 96, 0.6);
|
||||
}
|
||||
|
||||
.ne-node-header-exec.connected {
|
||||
background: #c04040;
|
||||
border-color: #c04040;
|
||||
}
|
||||
|
||||
/* ==================== Node Body 节点主体 ==================== */
|
||||
.ne-node-body {
|
||||
padding: 6px 0;
|
||||
background: var(--ne-node-bg-body);
|
||||
border-radius: 0 0 calc(var(--ne-node-border-radius) - 1px) calc(var(--ne-node-border-radius) - 1px);
|
||||
}
|
||||
|
||||
.ne-node-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
/* ==================== Pin Row 引脚行 ==================== */
|
||||
.ne-pin-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 20px;
|
||||
padding: 1px 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ne-pin-row.input {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
padding-left: 10px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.ne-pin-row.output {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: flex-start;
|
||||
padding-right: 10px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.ne-pin-label {
|
||||
font-size: 11px;
|
||||
color: #b0b0b0;
|
||||
white-space: nowrap;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.ne-pin-row.output .ne-pin-label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* ==================== Collapsed State 折叠状态 ==================== */
|
||||
.ne-node.collapsed .ne-node-body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ne-node.collapsed .ne-node-header {
|
||||
border-radius: calc(var(--ne-node-border-radius) - 1px);
|
||||
}
|
||||
|
||||
/* ==================== Comment Node 注释节点 ==================== */
|
||||
.ne-node.comment {
|
||||
background: rgba(50, 70, 50, 0.4);
|
||||
border: 1px dashed rgba(100, 140, 100, 0.6);
|
||||
min-width: 200px;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.ne-node.comment .ne-node-header {
|
||||
background: transparent;
|
||||
color: #90a090;
|
||||
}
|
||||
|
||||
.ne-node.comment .ne-node-body {
|
||||
background: transparent;
|
||||
color: #80a080;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ==================== Execution States 执行状态 ==================== */
|
||||
.ne-node.running {
|
||||
border-color: var(--ne-state-running);
|
||||
box-shadow: 0 0 0 1px var(--ne-state-running),
|
||||
0 0 12px rgba(255, 167, 38, 0.5);
|
||||
animation: ne-pulse 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.ne-node.success {
|
||||
border-color: var(--ne-state-success);
|
||||
box-shadow: 0 0 8px rgba(76, 175, 80, 0.4);
|
||||
}
|
||||
|
||||
.ne-node.error {
|
||||
border-color: var(--ne-state-error);
|
||||
box-shadow: 0 0 8px rgba(244, 67, 54, 0.4);
|
||||
}
|
||||
|
||||
@keyframes ne-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 0 1px var(--ne-state-running),
|
||||
0 0 12px rgba(255, 167, 38, 0.5);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 2px var(--ne-state-running),
|
||||
0 0 20px rgba(255, 167, 38, 0.7);
|
||||
}
|
||||
}
|
||||
104
packages/node-editor/src/styles/NodePin.css
Normal file
104
packages/node-editor/src/styles/NodePin.css
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Node Pin Styles
|
||||
* 节点引脚样式
|
||||
*/
|
||||
|
||||
/* ==================== Pin Base 引脚基础 ==================== */
|
||||
.ne-pin {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.1s ease;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ne-pin:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.ne-pin.compatible {
|
||||
animation: ne-pin-pulse 0.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* ==================== Pin Type Colors 引脚类型颜色 ==================== */
|
||||
.ne-pin.exec { color: var(--ne-pin-exec); }
|
||||
.ne-pin.bool { color: var(--ne-pin-bool); }
|
||||
.ne-pin.int { color: var(--ne-pin-int); }
|
||||
.ne-pin.float { color: var(--ne-pin-float); }
|
||||
.ne-pin.string { color: var(--ne-pin-string); }
|
||||
.ne-pin.vector2 { color: var(--ne-pin-vector2); }
|
||||
.ne-pin.vector3 { color: var(--ne-pin-vector3); }
|
||||
.ne-pin.vector4 { color: var(--ne-pin-vector4); }
|
||||
.ne-pin.color { color: var(--ne-pin-color); }
|
||||
.ne-pin.object { color: var(--ne-pin-object); }
|
||||
.ne-pin.array { color: var(--ne-pin-array); }
|
||||
.ne-pin.map { color: var(--ne-pin-map); }
|
||||
.ne-pin.struct { color: var(--ne-pin-struct); }
|
||||
.ne-pin.enum { color: var(--ne-pin-enum); }
|
||||
.ne-pin.delegate { color: var(--ne-pin-delegate); }
|
||||
.ne-pin.any { color: var(--ne-pin-any); }
|
||||
|
||||
/* ==================== Pin States 引脚状态 ==================== */
|
||||
.ne-pin.dragging-from {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
|
||||
.ne-pin.drop-target {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
|
||||
.ne-pin.invalid-target {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
/* ==================== Pin Animations 引脚动画 ==================== */
|
||||
@keyframes ne-pin-pulse {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Pin Value Input 引脚值输入 ==================== */
|
||||
.ne-pin-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.ne-pin-value-input {
|
||||
width: 50px;
|
||||
padding: 2px 4px;
|
||||
font-size: 10px;
|
||||
font-family: var(--ne-font-family-mono);
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 2px;
|
||||
color: #c0c0c0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ne-pin-value-input:focus {
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.ne-pin-value-checkbox {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
accent-color: var(--ne-pin-bool);
|
||||
}
|
||||
|
||||
.ne-pin-value-color {
|
||||
width: 20px;
|
||||
height: 12px;
|
||||
padding: 0;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
12
packages/node-editor/src/styles/index.css
Normal file
12
packages/node-editor/src/styles/index.css
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Node Editor Styles Entry Point
|
||||
* 节点编辑器样式入口
|
||||
*/
|
||||
|
||||
@import './variables.css';
|
||||
@import './Canvas.css';
|
||||
@import './GraphNode.css';
|
||||
@import './NodePin.css';
|
||||
@import './Connection.css';
|
||||
@import './ContextMenu.css';
|
||||
@import './Dialog.css';
|
||||
136
packages/node-editor/src/styles/variables.css
Normal file
136
packages/node-editor/src/styles/variables.css
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Node Editor Theme Variables
|
||||
* 节点编辑器主题变量
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* ==================== Background Colors 背景颜色 ==================== */
|
||||
--ne-canvas-bg: #141419;
|
||||
--ne-canvas-grid: #1a1a22;
|
||||
--ne-canvas-grid-major: #222230;
|
||||
|
||||
--ne-node-bg: rgba(12, 12, 16, 0.75);
|
||||
--ne-node-bg-body: rgba(8, 8, 12, 0.85);
|
||||
--ne-node-border: rgba(40, 40, 50, 0.6);
|
||||
--ne-node-border-selected: #e5a020;
|
||||
|
||||
/* ==================== Node Category Colors 节点类别颜色 ==================== */
|
||||
/* Event - Red gradient (like UE BeginOverlap) */
|
||||
--ne-category-event: #b81c1c;
|
||||
--ne-category-event-dark: #6b1010;
|
||||
|
||||
/* Function - Blue gradient */
|
||||
--ne-category-function: #1b6eb5;
|
||||
--ne-category-function-dark: #0d3d66;
|
||||
|
||||
/* Pure - Green/Teal gradient */
|
||||
--ne-category-pure: #3d8b3d;
|
||||
--ne-category-pure-dark: #1f5a1f;
|
||||
|
||||
/* Flow - Gray gradient */
|
||||
--ne-category-flow: #4a4a4a;
|
||||
--ne-category-flow-dark: #2a2a2a;
|
||||
|
||||
/* Variable - Purple gradient */
|
||||
--ne-category-variable: #7b3d9b;
|
||||
--ne-category-variable-dark: #4a1f66;
|
||||
|
||||
/* Literal - Gold/Orange gradient */
|
||||
--ne-category-literal: #9a7020;
|
||||
--ne-category-literal-dark: #5a4010;
|
||||
|
||||
/* Comment - Green gradient */
|
||||
--ne-category-comment: #3d6b3d;
|
||||
--ne-category-comment-dark: #2a4a2a;
|
||||
|
||||
/* Custom - Dark Gray gradient */
|
||||
--ne-category-custom: #3a3a3a;
|
||||
--ne-category-custom-dark: #1a1a1a;
|
||||
|
||||
/* ==================== Pin Type Colors 引脚类型颜色 ==================== */
|
||||
--ne-pin-exec: #ffffff;
|
||||
--ne-pin-bool: #8c0000;
|
||||
--ne-pin-int: #1cc4c4;
|
||||
--ne-pin-float: #7ecd32;
|
||||
--ne-pin-string: #e060e0;
|
||||
--ne-pin-vector2: #f0c030;
|
||||
--ne-pin-vector3: #f0c030;
|
||||
--ne-pin-vector4: #f0c030;
|
||||
--ne-pin-color: #e08030;
|
||||
--ne-pin-object: #00a0e0;
|
||||
--ne-pin-array: #7030c0;
|
||||
--ne-pin-map: #e060a0;
|
||||
--ne-pin-struct: #3060c0;
|
||||
--ne-pin-enum: #10a090;
|
||||
--ne-pin-delegate: #c01030;
|
||||
--ne-pin-any: #707070;
|
||||
|
||||
/* ==================== Connection Colors 连接线颜色 ==================== */
|
||||
--ne-connection-exec: #ffffff;
|
||||
--ne-connection-data: #888888;
|
||||
--ne-connection-hover: #00aaff;
|
||||
--ne-connection-selected: #ffcc00;
|
||||
--ne-connection-invalid: #ff4444;
|
||||
--ne-connection-preview: rgba(255, 255, 255, 0.5);
|
||||
|
||||
/* ==================== Text Colors 文字颜色 ==================== */
|
||||
--ne-text-primary: #c0c0c0;
|
||||
--ne-text-secondary: #909090;
|
||||
--ne-text-muted: #606060;
|
||||
--ne-text-title: #ffffff;
|
||||
--ne-text-subtitle: #cccccc;
|
||||
|
||||
/* ==================== State Colors 状态颜色 ==================== */
|
||||
--ne-state-success: #4caf50;
|
||||
--ne-state-warning: #ff9800;
|
||||
--ne-state-error: #f44336;
|
||||
--ne-state-info: #2196f3;
|
||||
--ne-state-running: #ffa726;
|
||||
|
||||
/* ==================== Shadow 阴影 ==================== */
|
||||
--ne-shadow-node: 0 4px 12px rgba(0, 0, 0, 0.5),
|
||||
0 0 0 1px rgba(0, 0, 0, 0.8),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||
--ne-shadow-node-hover: 0 6px 16px rgba(0, 0, 0, 0.6);
|
||||
--ne-shadow-node-selected: 0 0 0 2px var(--ne-node-border-selected),
|
||||
0 0 20px rgba(245, 166, 35, 0.3);
|
||||
--ne-shadow-pin: 0 0 4px rgba(0, 0, 0, 0.5);
|
||||
--ne-shadow-pin-hover: 0 0 8px currentColor;
|
||||
|
||||
/* ==================== Sizing 尺寸 ==================== */
|
||||
--ne-node-min-width: 200px;
|
||||
--ne-node-max-width: 350px;
|
||||
--ne-node-border-radius: 6px;
|
||||
--ne-node-header-height: 28px;
|
||||
--ne-node-padding: 8px 0;
|
||||
|
||||
--ne-pin-size: 10px;
|
||||
--ne-pin-size-exec: 12px;
|
||||
--ne-pin-spacing: 22px;
|
||||
--ne-pin-hit-area: 24px;
|
||||
|
||||
--ne-connection-width: 2px;
|
||||
--ne-connection-width-hover: 3px;
|
||||
--ne-connection-width-exec: 3px;
|
||||
|
||||
/* ==================== Typography 字体 ==================== */
|
||||
--ne-font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
|
||||
--ne-font-family-mono: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
--ne-font-size-title: 12px;
|
||||
--ne-font-size-body: 11px;
|
||||
--ne-font-size-small: 10px;
|
||||
|
||||
/* ==================== Animation 动画 ==================== */
|
||||
--ne-transition-fast: 0.1s ease;
|
||||
--ne-transition-normal: 0.15s ease;
|
||||
--ne-transition-slow: 0.3s ease;
|
||||
|
||||
/* ==================== Z-Index 层级 ==================== */
|
||||
--ne-z-grid: 0;
|
||||
--ne-z-connections: 1;
|
||||
--ne-z-nodes: 2;
|
||||
--ne-z-dragging: 100;
|
||||
--ne-z-menu: 1000;
|
||||
--ne-z-tooltip: 1001;
|
||||
--ne-z-dialog: 2000;
|
||||
}
|
||||
Reference in New Issue
Block a user