d8b935317d
抽出素材栏、生成器、舞台工具栏和画布世界视图 补充各拆分视图的聚焦测试 更新 TRACKING.md 记录第三十四阶段验证
320 lines
10 KiB
TypeScript
320 lines
10 KiB
TypeScript
import { PlatformFloatingMenu, PlatformFloatingMenuItem } from '../common/PlatformFloatingMenu';
|
|
import type {
|
|
CanvasClipboard,
|
|
CanvasContextMenuState,
|
|
CanvasLayer,
|
|
CanvasViewport,
|
|
ImageContextMenuState,
|
|
} from './ImageCanvasEditorTypes';
|
|
|
|
type ImageCanvasContextMenusViewProps = {
|
|
viewport: CanvasViewport;
|
|
contextMenu: CanvasContextMenuState | null;
|
|
canvasClipboard: CanvasClipboard | null;
|
|
imageContextMenu: ImageContextMenuState | null;
|
|
imageContextMenuLayer: CanvasLayer | null;
|
|
contextShouldShowLayer: boolean;
|
|
contextShouldUnlockLayer: boolean;
|
|
onPasteCanvasClipboard: (canvasPoint?: { x: number; y: number }) => void;
|
|
onCopyContextLayers: (options?: { cut?: boolean }) => void;
|
|
onDuplicateContextLayers: () => void;
|
|
onMoveContextLayers: (mode: 'up' | 'down' | 'top' | 'bottom') => void;
|
|
onGroupContextLayers: () => void;
|
|
onUngroupContextLayers: () => void;
|
|
onToggleContextLayerVisibility: () => void;
|
|
onToggleContextLayerLock: () => void;
|
|
onFlipContextLayers: (axis: 'x' | 'y') => void;
|
|
onExportContextLayer: () => void;
|
|
onDeleteContextLayers: () => void;
|
|
onDeleteLayerById: (layerId: string | null) => void;
|
|
onCloseContextMenu: () => void;
|
|
onCloseImageContextMenu: () => void;
|
|
onUpdateScaleFromCenter: (nextScale: number) => void;
|
|
onFitLayers: () => void;
|
|
onOpenQuickEditPanel: (layer: CanvasLayer) => void;
|
|
onOpenLayerMetadata: (layer: CanvasLayer) => void;
|
|
onOpenCharacterAnimationPanel: (layer: CanvasLayer) => void;
|
|
};
|
|
|
|
export function ImageCanvasContextMenusView({
|
|
viewport,
|
|
contextMenu,
|
|
canvasClipboard,
|
|
imageContextMenu,
|
|
imageContextMenuLayer,
|
|
contextShouldShowLayer,
|
|
contextShouldUnlockLayer,
|
|
onPasteCanvasClipboard,
|
|
onCopyContextLayers,
|
|
onDuplicateContextLayers,
|
|
onMoveContextLayers,
|
|
onGroupContextLayers,
|
|
onUngroupContextLayers,
|
|
onToggleContextLayerVisibility,
|
|
onToggleContextLayerLock,
|
|
onFlipContextLayers,
|
|
onExportContextLayer,
|
|
onDeleteContextLayers,
|
|
onDeleteLayerById,
|
|
onCloseContextMenu,
|
|
onCloseImageContextMenu,
|
|
onUpdateScaleFromCenter,
|
|
onFitLayers,
|
|
onOpenQuickEditPanel,
|
|
onOpenLayerMetadata,
|
|
onOpenCharacterAnimationPanel,
|
|
}: ImageCanvasContextMenusViewProps) {
|
|
return (
|
|
<>
|
|
{contextMenu ? (
|
|
<div
|
|
className="image-canvas-editor__context-menu"
|
|
role="menu"
|
|
aria-label={
|
|
contextMenu.kind === 'blank' ? '画布右键菜单' : '图片功能面板'
|
|
}
|
|
style={{
|
|
left: contextMenu.x,
|
|
top: contextMenu.y,
|
|
}}
|
|
onContextMenu={(event) => event.preventDefault()}
|
|
onPointerDown={(event) => event.stopPropagation()}
|
|
>
|
|
{contextMenu.kind === 'blank' ? (
|
|
<>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
disabled={!canvasClipboard?.layers.length}
|
|
onClick={() => onPasteCanvasClipboard(contextMenu.canvasPoint)}
|
|
>
|
|
粘贴
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => {
|
|
onUpdateScaleFromCenter(viewport.scale * 1.16);
|
|
onCloseContextMenu();
|
|
}}
|
|
>
|
|
放大
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => {
|
|
onUpdateScaleFromCenter(viewport.scale * 0.86);
|
|
onCloseContextMenu();
|
|
}}
|
|
>
|
|
缩小
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => {
|
|
onFitLayers();
|
|
onCloseContextMenu();
|
|
}}
|
|
>
|
|
显示画布所有元素
|
|
</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onCopyContextLayers()}
|
|
>
|
|
复制
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onCopyContextLayers({ cut: true })}
|
|
>
|
|
剪切
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
disabled={!canvasClipboard?.layers.length}
|
|
onClick={() => onPasteCanvasClipboard(contextMenu.canvasPoint)}
|
|
>
|
|
粘贴
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={onDuplicateContextLayers}
|
|
>
|
|
创建副本
|
|
</button>
|
|
<hr />
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onMoveContextLayers('up')}
|
|
>
|
|
上移一层
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onMoveContextLayers('down')}
|
|
>
|
|
下移一层
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onMoveContextLayers('top')}
|
|
>
|
|
置于顶层
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onMoveContextLayers('bottom')}
|
|
>
|
|
移动至底层
|
|
</button>
|
|
<hr />
|
|
<button type="button" role="menuitem" onClick={onGroupContextLayers}>
|
|
创建组
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={onUngroupContextLayers}
|
|
>
|
|
解除组
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={onToggleContextLayerVisibility}
|
|
>
|
|
{contextShouldShowLayer ? '显示' : '隐藏'}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={onToggleContextLayerLock}
|
|
>
|
|
{contextShouldUnlockLayer ? '解锁' : '锁定'}
|
|
</button>
|
|
<hr />
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onFlipContextLayers('x')}
|
|
>
|
|
水平翻转
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onFlipContextLayers('y')}
|
|
>
|
|
垂直翻转
|
|
</button>
|
|
<button type="button" role="menuitem" onClick={onExportContextLayer}>
|
|
导出为
|
|
</button>
|
|
<hr />
|
|
{imageContextMenuLayer ? (
|
|
<>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => onOpenQuickEditPanel(imageContextMenuLayer)}
|
|
>
|
|
快速编辑
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => {
|
|
onOpenLayerMetadata(imageContextMenuLayer);
|
|
onCloseContextMenu();
|
|
onCloseImageContextMenu();
|
|
}}
|
|
>
|
|
查看图片信息
|
|
</button>
|
|
{imageContextMenuLayer.assetKind === 'character' ? (
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() =>
|
|
onOpenCharacterAnimationPanel(imageContextMenuLayer)
|
|
}
|
|
>
|
|
生成动画
|
|
</button>
|
|
) : null}
|
|
<hr />
|
|
</>
|
|
) : null}
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
className="image-canvas-editor__context-menu-danger"
|
|
onClick={onDeleteContextLayers}
|
|
>
|
|
删除
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
|
|
{imageContextMenu && imageContextMenuLayer && !contextMenu ? (
|
|
<div
|
|
className="image-canvas-editor__context-menu"
|
|
style={{
|
|
left: imageContextMenu.x,
|
|
top: imageContextMenu.y,
|
|
}}
|
|
onPointerDown={(event) => event.stopPropagation()}
|
|
>
|
|
<PlatformFloatingMenu label="图片功能面板" placement="bottom-start">
|
|
<PlatformFloatingMenuItem
|
|
className="image-canvas-editor__context-menu-item"
|
|
onClick={() => onOpenQuickEditPanel(imageContextMenuLayer)}
|
|
>
|
|
快速编辑
|
|
</PlatformFloatingMenuItem>
|
|
<PlatformFloatingMenuItem
|
|
className="image-canvas-editor__context-menu-item"
|
|
onClick={() => {
|
|
onOpenLayerMetadata(imageContextMenuLayer);
|
|
onCloseImageContextMenu();
|
|
}}
|
|
>
|
|
查看图片信息
|
|
</PlatformFloatingMenuItem>
|
|
{imageContextMenuLayer.assetKind === 'character' ? (
|
|
<PlatformFloatingMenuItem
|
|
className="image-canvas-editor__context-menu-item"
|
|
onClick={() => onOpenCharacterAnimationPanel(imageContextMenuLayer)}
|
|
>
|
|
生成动画
|
|
</PlatformFloatingMenuItem>
|
|
) : null}
|
|
<PlatformFloatingMenuItem
|
|
className="image-canvas-editor__context-menu-item"
|
|
onClick={() => onDeleteLayerById(imageContextMenuLayer.id)}
|
|
>
|
|
删除图片
|
|
</PlatformFloatingMenuItem>
|
|
</PlatformFloatingMenu>
|
|
</div>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|