This commit is contained in:
xsxx03-art
2026-06-16 20:31:34 +08:00
parent 5db13a7d69
commit 944bc26fb9
21 changed files with 356 additions and 87 deletions
+32 -11
View File
@@ -12,6 +12,13 @@
}
root.MxpicCanvasHelpers = helpers;
})(typeof window !== 'undefined' ? window : globalThis, function () {
// Global origin for YAML coordinate export/import so YAML values always match
// the RightPanel display coordinate system.
let __exportOriginX = null;
let __exportOriginY = null;
var setExportOrigin = (x, y) => { __exportOriginX = x; __exportOriginY = y; };
var getExportOrigin = () => ({ x: __exportOriginX, y: __exportOriginY });
// Label used by the canvas to represent generated mxpic_forge components.
const FORGE_COMPONENT_LABEL = 'generate with mxpic_forge';
// Serialized component type used when saving mxpic_forge-generated components.
@@ -651,10 +658,20 @@
return JSON.stringify(String(value));
};
// Convert canvas Y coordinates into layout Y coordinates.
const canvasToLayoutY = (value) => -Number(value || 0);
// Convert layout Y coordinates back into canvas Y coordinates.
const layoutToCanvasY = (value) => -Number(value || 0);
// Convert canvas coordinates into layout/display coordinates.
// When origin is set, uses the RightPanel formula: displayY = originY - rfY
// Falls back to simple negation for backward compatibility.
const canvasToLayoutY = (value) => { const v = Number(value || 0); return __exportOriginY != null ? __exportOriginY - v : -v; };
const canvasToLayoutX = (value) => { const v = Number(value || 0); return __exportOriginX != null ? v - __exportOriginX : v; };
// Convert layout/display coordinates back into canvas coordinates.
// Uses self-inverse formula for Y: rfY = originY - displayY (same as above).
// Import: layout/display coords → canvas coords. Optional originY/originX allow
// per-file overrides (e.g. from a YAML canvas_origin field). When omitted the
// module-level origin is used; null origin falls back to simple negation / pass-through.
const layoutToCanvasY = (value, originY) => { const v = Number(value || 0); const oy = originY !== undefined ? originY : __exportOriginY; return oy != null ? oy - v : -v; };
const layoutToCanvasX = (value, originX) => { const v = Number(value || 0); const ox = originX !== undefined ? originX : __exportOriginX; return ox != null ? v + ox : v; };
// Serialize nested component settings into YAML blocks.
const buildSettingsYaml = (settings, indent) => {
@@ -677,8 +694,8 @@
: '\n settings:\n length:';
return ` ${instanceName}:
component: ${componentValue}
x: ${Number(position.x || 0).toFixed(1)}
component: "${componentValue}"
x: ${canvasToLayoutX(position.x).toFixed(1)}
y: ${canvasToLayoutY(position.y).toFixed(1)}
rotation: ${Number(rotation || 0).toFixed(1)}
flip: ${flip ? 1 : 0}
@@ -908,7 +925,7 @@
// Convert standalone port nodes into page-level layout pins.
const buildPageComponentPins = (port, nodes) => {
const portNodes = (nodes || []).filter(isPortElementNode);
const portNodes = (nodes || []).filter(n => n.id === 'page-port');
if (portNodes.length > 0) {
return portNodes.reduce((pins, node) => {
const data = node.data || {};
@@ -962,7 +979,7 @@
${data.layer ? `layer: ${data.layer}` : 'layer: WG_CORE'}
element: ${info.element}
pin: ${info.pin}
x: ${Number(info.x || 0).toFixed(1)}
x: ${canvasToLayoutX(info.x).toFixed(1)}
y: ${canvasToLayoutY(info.y).toFixed(1)}
angle: ${Number(info.a || 0).toFixed(1)}
width: ${Number(info.width || 0.5)}${description}`;
@@ -977,7 +994,7 @@
// Serialize built-in port and anchor nodes into layout element metadata.
const buildElementsYaml = (nodes) => {
const elementNodes = (nodes || []).filter(isElementNode);
const elementNodes = (nodes || []).filter(n => isElementNode(n) && n.id !== 'page-port');
if (elementNodes.length === 0) return 'elements: {}';
const lines = elementNodes.map(node => {
const data = node.data || {};
@@ -990,7 +1007,7 @@
.join('\n');
return ` ${name}:
type: ${data.elementType}
x: ${Number((node.position && node.position.x) || 0).toFixed(1)}
x: ${canvasToLayoutX((node.position && node.position.x) || 0).toFixed(1)}
y: ${canvasToLayoutY((node.position && node.position.y) || 0).toFixed(1)}
angle: ${Number(angle || 0).toFixed(1)}
pin_number: ${portNumber}
@@ -1055,7 +1072,7 @@ ${pinLines}`;
const storedPoints = Array.isArray(edge.data && edge.data.points) ? edge.data.points : [];
const points = storedPoints.length >= 2 ? getEdgeRoutePoints(edge, nodeMap) : [];
const pointsYaml = points.length > 0
? `\n points:\n${points.map(point => ` - x: ${Number(point.x || 0).toFixed(1)}\n y: ${canvasToLayoutY(point.y).toFixed(1)}`).join('\n')}`
? `\n points:\n${points.map(point => ` - x: ${canvasToLayoutX(point.x).toFixed(1)}\n y: ${canvasToLayoutY(point.y).toFixed(1)}`).join('\n')}`
: '';
const isFreeRoute = Boolean(edge.data && edge.data.freeRoute) || (!sourceNode && !targetNode && points.length >= 2);
const linkYaml = isFreeRoute
@@ -1311,8 +1328,12 @@ bundles:${groupsYaml ? `\n${groupsYaml}` : ' {}'}`;
DEFAULT_FORGE_ARGUMENTS,
FALLBACK_TECHNOLOGY_MANIFEST,
FREE_WIRES_BUNDLE_GROUP,
setExportOrigin,
getExportOrigin,
canvasToLayoutY,
canvasToLayoutX,
layoutToCanvasY,
layoutToCanvasX,
createForgeArguments,
createRouteSettings,
updateRouteField,