mirror of
https://github.com/penpot/penpot-exporter-figma-plugin.git
synced 2024-12-22 05:33:02 -05:00
remove base rotation and calculate it instead (#178)
This commit is contained in:
parent
8eb2b1a1be
commit
4e5d01adb3
19 changed files with 109 additions and 139 deletions
|
@ -6,16 +6,13 @@ const nodeActsAsMask = (node: SceneNode): boolean => {
|
||||||
return 'isMask' in node && node.isMask;
|
return 'isMask' in node && node.isMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformChildren = async (
|
export const transformChildren = async (node: ChildrenMixin): Promise<Children> => {
|
||||||
node: ChildrenMixin,
|
|
||||||
baseRotation: number = 0
|
|
||||||
): Promise<Children> => {
|
|
||||||
const maskIndex = node.children.findIndex(nodeActsAsMask);
|
const maskIndex = node.children.findIndex(nodeActsAsMask);
|
||||||
const containsMask = maskIndex !== -1;
|
const containsMask = maskIndex !== -1;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
children: containsMask
|
children: containsMask
|
||||||
? await translateMaskChildren(node.children, maskIndex, baseRotation)
|
? await translateMaskChildren(node.children, maskIndex)
|
||||||
: await translateChildren(node.children, baseRotation)
|
: await translateChildren(node.children)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { translateRotation, translateZeroRotation } from '@plugin/translators';
|
import { translateRotation, translateZeroRotation } from '@plugin/translators';
|
||||||
import { applyInverseRotation, hasRotation } from '@plugin/utils';
|
import { applyInverseRotation, getRotation, hasRotation } from '@plugin/utils';
|
||||||
|
|
||||||
import { ShapeBaseAttributes, ShapeGeomAttributes } from '@ui/lib/types/shapes/shape';
|
import { ShapeBaseAttributes, ShapeGeomAttributes } from '@ui/lib/types/shapes/shape';
|
||||||
|
|
||||||
export const transformRotation = (
|
export const transformRotation = (
|
||||||
node: LayoutMixin,
|
node: LayoutMixin
|
||||||
baseRotation: number
|
|
||||||
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => {
|
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => {
|
||||||
const rotation = node.rotation + baseRotation;
|
const rotation = getRotation(node.absoluteTransform);
|
||||||
|
|
||||||
if (!hasRotation(rotation)) {
|
if (!hasRotation(rotation)) {
|
||||||
return translateZeroRotation();
|
return translateZeroRotation();
|
||||||
|
@ -17,13 +16,12 @@ export const transformRotation = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformRotationAndPosition = (
|
export const transformRotationAndPosition = (
|
||||||
node: LayoutMixin,
|
node: LayoutMixin
|
||||||
baseRotation: number
|
|
||||||
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> &
|
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> &
|
||||||
Pick<ShapeGeomAttributes, 'x' | 'y'> => {
|
Pick<ShapeGeomAttributes, 'x' | 'y'> => {
|
||||||
const rotation = node.rotation + baseRotation;
|
|
||||||
const x = node.absoluteTransform[0][2];
|
const x = node.absoluteTransform[0][2];
|
||||||
const y = node.absoluteTransform[1][2];
|
const y = node.absoluteTransform[1][2];
|
||||||
|
const rotation = getRotation(node.absoluteTransform);
|
||||||
|
|
||||||
if (!hasRotation(rotation) || !node.absoluteBoundingBox) {
|
if (!hasRotation(rotation) || !node.absoluteBoundingBox) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { translateCommands, translateWindingRule } from '@plugin/translators/vec
|
||||||
|
|
||||||
import { PathShape } from '@ui/lib/types/shapes/pathShape';
|
import { PathShape } from '@ui/lib/types/shapes/pathShape';
|
||||||
|
|
||||||
export const transformVectorPaths = (node: VectorNode, baseRotation: number): PathShape[] => {
|
export const transformVectorPaths = (node: VectorNode): PathShape[] => {
|
||||||
const pathShapes = node.vectorPaths
|
const pathShapes = node.vectorPaths
|
||||||
.filter((vectorPath, index) => {
|
.filter((vectorPath, index) => {
|
||||||
return (
|
return (
|
||||||
|
@ -22,7 +22,7 @@ export const transformVectorPaths = (node: VectorNode, baseRotation: number): Pa
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.map((vectorPath, index) =>
|
.map((vectorPath, index) =>
|
||||||
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index], baseRotation)
|
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index])
|
||||||
);
|
);
|
||||||
|
|
||||||
const geometryShapes = node.fillGeometry
|
const geometryShapes = node.fillGeometry
|
||||||
|
@ -32,7 +32,7 @@ export const transformVectorPaths = (node: VectorNode, baseRotation: number): Pa
|
||||||
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
|
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map(geometry => transformVectorPath(node, geometry, undefined, baseRotation));
|
.map(geometry => transformVectorPath(node, geometry, undefined));
|
||||||
|
|
||||||
return [...geometryShapes, ...pathShapes];
|
return [...geometryShapes, ...pathShapes];
|
||||||
};
|
};
|
||||||
|
@ -58,15 +58,14 @@ const nodeHasFills = (
|
||||||
const transformVectorPath = (
|
const transformVectorPath = (
|
||||||
node: VectorNode,
|
node: VectorNode,
|
||||||
vectorPath: VectorPath,
|
vectorPath: VectorPath,
|
||||||
vectorRegion: VectorRegion | undefined,
|
vectorRegion: VectorRegion | undefined
|
||||||
baseRotation: number
|
|
||||||
): PathShape => {
|
): PathShape => {
|
||||||
const normalizedPaths = parseSVG(vectorPath.data);
|
const normalizedPaths = parseSVG(vectorPath.data);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'path',
|
type: 'path',
|
||||||
name: 'svg-path',
|
name: 'svg-path',
|
||||||
content: translateCommands(node, normalizedPaths, baseRotation),
|
content: translateCommands(node, normalizedPaths),
|
||||||
fills:
|
fills:
|
||||||
vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills),
|
vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills),
|
||||||
svgAttrs: {
|
svgAttrs: {
|
||||||
|
|
|
@ -16,21 +16,18 @@ import { translateBoolType } from '@plugin/translators';
|
||||||
|
|
||||||
import { BoolShape } from '@ui/lib/types/shapes/boolShape';
|
import { BoolShape } from '@ui/lib/types/shapes/boolShape';
|
||||||
|
|
||||||
export const transformBooleanNode = async (
|
export const transformBooleanNode = async (node: BooleanOperationNode): Promise<BoolShape> => {
|
||||||
node: BooleanOperationNode,
|
|
||||||
baseRotation: number
|
|
||||||
): Promise<BoolShape> => {
|
|
||||||
return {
|
return {
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
boolType: translateBoolType(node.booleanOperation),
|
boolType: translateBoolType(node.booleanOperation),
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...(await transformChildren(node, baseRotation)),
|
...(await transformChildren(node)),
|
||||||
...transformFills(node),
|
...transformFills(node),
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformStrokes(node),
|
...transformStrokes(node),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...transformProportion(node),
|
...transformProportion(node),
|
||||||
|
|
|
@ -18,10 +18,7 @@ import {
|
||||||
|
|
||||||
import { ComponentRoot } from '@ui/types';
|
import { ComponentRoot } from '@ui/types';
|
||||||
|
|
||||||
export const transformComponentNode = async (
|
export const transformComponentNode = async (node: ComponentNode): Promise<ComponentRoot> => {
|
||||||
node: ComponentNode,
|
|
||||||
baseRotation: number
|
|
||||||
): Promise<ComponentRoot> => {
|
|
||||||
componentsLibrary.register(node.id, {
|
componentsLibrary.register(node.id, {
|
||||||
type: 'component',
|
type: 'component',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
|
@ -36,9 +33,9 @@ export const transformComponentNode = async (
|
||||||
...transformProportion(node),
|
...transformProportion(node),
|
||||||
...transformLayoutAttributes(node, true),
|
...transformLayoutAttributes(node, true),
|
||||||
...transformCornerRadius(node),
|
...transformCornerRadius(node),
|
||||||
...(await transformChildren(node, node.rotation + baseRotation)),
|
...(await transformChildren(node)),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformConstraints(node),
|
...transformConstraints(node),
|
||||||
...transformAutoLayout(node)
|
...transformAutoLayout(node)
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
|
|
||||||
import { CircleShape } from '@ui/lib/types/shapes/circleShape';
|
import { CircleShape } from '@ui/lib/types/shapes/circleShape';
|
||||||
|
|
||||||
export const transformEllipseNode = (node: EllipseNode, baseRotation: number): CircleShape => {
|
export const transformEllipseNode = (node: EllipseNode): CircleShape => {
|
||||||
return {
|
return {
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
|
@ -24,7 +24,7 @@ export const transformEllipseNode = (node: EllipseNode, baseRotation: number): C
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformStrokes(node),
|
...transformStrokes(node),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...transformProportion(node),
|
...transformProportion(node),
|
||||||
|
|
|
@ -24,18 +24,15 @@ const isSectionNode = (node: FrameNode | SectionNode | ComponentSetNode): node i
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformFrameNode = async (
|
export const transformFrameNode = async (
|
||||||
node: FrameNode | SectionNode | ComponentSetNode,
|
node: FrameNode | SectionNode | ComponentSetNode
|
||||||
baseRotation: number
|
|
||||||
): Promise<FrameShape> => {
|
): Promise<FrameShape> => {
|
||||||
let frameSpecificAttributes: Partial<FrameShape> = {};
|
let frameSpecificAttributes: Partial<FrameShape> = {};
|
||||||
let referencePoint: Point = { x: node.absoluteTransform[0][2], y: node.absoluteTransform[1][2] };
|
let referencePoint: Point = { x: node.absoluteTransform[0][2], y: node.absoluteTransform[1][2] };
|
||||||
let rotation = baseRotation;
|
|
||||||
|
|
||||||
if (!isSectionNode(node)) {
|
if (!isSectionNode(node)) {
|
||||||
const { x, y, ...transformAndRotation } = transformRotationAndPosition(node, baseRotation);
|
const { x, y, ...transformAndRotation } = transformRotationAndPosition(node);
|
||||||
|
|
||||||
referencePoint = { x, y };
|
referencePoint = { x, y };
|
||||||
rotation += node.rotation;
|
|
||||||
|
|
||||||
// Figma API does not expose strokes, blend modes, corner radius, or constraint proportions for sections,
|
// Figma API does not expose strokes, blend modes, corner radius, or constraint proportions for sections,
|
||||||
// they plan to add it in the future. Refactor this when available.
|
// they plan to add it in the future. Refactor this when available.
|
||||||
|
@ -63,7 +60,7 @@ export const transformFrameNode = async (
|
||||||
...referencePoint,
|
...referencePoint,
|
||||||
...frameSpecificAttributes,
|
...frameSpecificAttributes,
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...(await transformChildren(node, rotation)),
|
...(await transformChildren(node)),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformOverrides(node)
|
...transformOverrides(node)
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,29 +11,25 @@ import { transformChildren } from '@plugin/transformers/partials';
|
||||||
|
|
||||||
import { GroupShape } from '@ui/lib/types/shapes/groupShape';
|
import { GroupShape } from '@ui/lib/types/shapes/groupShape';
|
||||||
|
|
||||||
export const transformGroupNode = async (
|
export const transformGroupNode = async (node: GroupNode): Promise<GroupShape> => {
|
||||||
node: GroupNode,
|
|
||||||
baseRotation: number
|
|
||||||
): Promise<GroupShape> => {
|
|
||||||
return {
|
return {
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...transformGroupNodeLike(node, baseRotation),
|
...transformGroupNodeLike(node),
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...(await transformChildren(node, baseRotation)),
|
...(await transformChildren(node)),
|
||||||
...transformOverrides(node)
|
...transformOverrides(node)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformGroupNodeLike = (
|
export const transformGroupNodeLike = (
|
||||||
node: BaseNodeMixin & LayoutMixin & SceneNodeMixin,
|
node: BaseNodeMixin & LayoutMixin & SceneNodeMixin
|
||||||
baseRotation: number
|
|
||||||
): GroupShape => {
|
): GroupShape => {
|
||||||
return {
|
return {
|
||||||
type: 'group',
|
type: 'group',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformSceneNode(node)
|
...transformSceneNode(node)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,8 +21,7 @@ import {
|
||||||
import { ComponentInstance, ComponentTextPropertyOverride } from '@ui/types';
|
import { ComponentInstance, ComponentTextPropertyOverride } from '@ui/types';
|
||||||
|
|
||||||
export const transformInstanceNode = async (
|
export const transformInstanceNode = async (
|
||||||
node: InstanceNode,
|
node: InstanceNode
|
||||||
baseRotation: number
|
|
||||||
): Promise<ComponentInstance | undefined> => {
|
): Promise<ComponentInstance | undefined> => {
|
||||||
const mainComponent = await node.getMainComponentAsync();
|
const mainComponent = await node.getMainComponentAsync();
|
||||||
if (mainComponent === null) {
|
if (mainComponent === null) {
|
||||||
|
@ -62,10 +61,10 @@ export const transformInstanceNode = async (
|
||||||
...transformLayoutAttributes(node, true),
|
...transformLayoutAttributes(node, true),
|
||||||
...transformCornerRadius(node),
|
...transformCornerRadius(node),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformConstraints(node),
|
...transformConstraints(node),
|
||||||
...transformAutoLayout(node),
|
...transformAutoLayout(node),
|
||||||
...(await transformChildren(node, node.rotation + baseRotation)),
|
...(await transformChildren(node)),
|
||||||
...transformOverrides(node)
|
...transformOverrides(node)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,11 +20,11 @@ import { Segment } from '@ui/lib/types/shapes/pathShape';
|
||||||
*
|
*
|
||||||
* To represent the line rotated we do take into account the rotation of the line, but only in its content.
|
* To represent the line rotated we do take into account the rotation of the line, but only in its content.
|
||||||
*/
|
*/
|
||||||
export const transformLineNode = (node: LineNode, baseRotation: number): PathShape => {
|
export const transformLineNode = (node: LineNode): PathShape => {
|
||||||
return {
|
return {
|
||||||
type: 'path',
|
type: 'path',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
content: translateLineNode(node, baseRotation),
|
content: translateLineNode(node),
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...transformStrokes(node),
|
...transformStrokes(node),
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
|
@ -37,23 +37,19 @@ export const transformLineNode = (node: LineNode, baseRotation: number): PathSha
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const translateLineNode = (node: LineNode, baseRotation: number): Segment[] => {
|
const translateLineNode = (node: LineNode): Segment[] => {
|
||||||
return translateCommands(
|
return translateCommands(node, [
|
||||||
node,
|
{
|
||||||
[
|
x: 0,
|
||||||
{
|
y: 0,
|
||||||
x: 0,
|
command: 'moveto',
|
||||||
y: 0,
|
code: 'M'
|
||||||
command: 'moveto',
|
},
|
||||||
code: 'M'
|
{
|
||||||
},
|
x: node.width,
|
||||||
{
|
y: 0,
|
||||||
x: node.width,
|
command: 'lineto',
|
||||||
y: 0,
|
code: 'L'
|
||||||
command: 'lineto',
|
}
|
||||||
code: 'L'
|
]);
|
||||||
}
|
|
||||||
],
|
|
||||||
baseRotation
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,14 +17,11 @@ import { translateCommands } from '@plugin/translators/vectors';
|
||||||
|
|
||||||
import { PathShape, Segment } from '@ui/lib/types/shapes/pathShape';
|
import { PathShape, Segment } from '@ui/lib/types/shapes/pathShape';
|
||||||
|
|
||||||
export const transformPathNode = (
|
export const transformPathNode = (node: StarNode | PolygonNode): PathShape => {
|
||||||
node: StarNode | PolygonNode,
|
|
||||||
baseRotation: number
|
|
||||||
): PathShape => {
|
|
||||||
return {
|
return {
|
||||||
type: 'path',
|
type: 'path',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
content: translatePathNode(node, baseRotation),
|
content: translatePathNode(node),
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...transformFills(node),
|
...transformFills(node),
|
||||||
...transformStrokes(node),
|
...transformStrokes(node),
|
||||||
|
@ -32,12 +29,12 @@ export const transformPathNode = (
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...transformProportion(node),
|
...transformProportion(node),
|
||||||
...transformRotation(node, baseRotation),
|
...transformRotation(node),
|
||||||
...transformLayoutAttributes(node),
|
...transformLayoutAttributes(node),
|
||||||
...transformConstraints(node),
|
...transformConstraints(node),
|
||||||
...transformOverrides(node)
|
...transformOverrides(node)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const translatePathNode = (node: StarNode | PolygonNode, baseRotation: number): Segment[] =>
|
const translatePathNode = (node: StarNode | PolygonNode): Segment[] =>
|
||||||
translateCommands(node, parseSVG(node.fillGeometry[0].data), baseRotation);
|
translateCommands(node, parseSVG(node.fillGeometry[0].data));
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
|
|
||||||
import { RectShape } from '@ui/lib/types/shapes/rectShape';
|
import { RectShape } from '@ui/lib/types/shapes/rectShape';
|
||||||
|
|
||||||
export const transformRectangleNode = (node: RectangleNode, baseRotation: number): RectShape => {
|
export const transformRectangleNode = (node: RectangleNode): RectShape => {
|
||||||
return {
|
return {
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
|
@ -25,7 +25,7 @@ export const transformRectangleNode = (node: RectangleNode, baseRotation: number
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformStrokes(node),
|
...transformStrokes(node),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...transformProportion(node),
|
...transformProportion(node),
|
||||||
|
|
|
@ -14,10 +14,7 @@ import {
|
||||||
transformVectorNode
|
transformVectorNode
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
export const transformSceneNode = async (
|
export const transformSceneNode = async (node: SceneNode): Promise<PenpotNode | undefined> => {
|
||||||
node: SceneNode,
|
|
||||||
baseRotation: number = 0
|
|
||||||
): Promise<PenpotNode | undefined> => {
|
|
||||||
let penpotNode: PenpotNode | undefined;
|
let penpotNode: PenpotNode | undefined;
|
||||||
|
|
||||||
figma.ui.postMessage({
|
figma.ui.postMessage({
|
||||||
|
@ -27,40 +24,40 @@ export const transformSceneNode = async (
|
||||||
|
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'RECTANGLE':
|
case 'RECTANGLE':
|
||||||
penpotNode = transformRectangleNode(node, baseRotation);
|
penpotNode = transformRectangleNode(node);
|
||||||
break;
|
break;
|
||||||
case 'ELLIPSE':
|
case 'ELLIPSE':
|
||||||
penpotNode = transformEllipseNode(node, baseRotation);
|
penpotNode = transformEllipseNode(node);
|
||||||
break;
|
break;
|
||||||
case 'SECTION':
|
case 'SECTION':
|
||||||
case 'FRAME':
|
case 'FRAME':
|
||||||
case 'COMPONENT_SET':
|
case 'COMPONENT_SET':
|
||||||
penpotNode = await transformFrameNode(node, baseRotation);
|
penpotNode = await transformFrameNode(node);
|
||||||
break;
|
break;
|
||||||
case 'GROUP':
|
case 'GROUP':
|
||||||
penpotNode = await transformGroupNode(node, baseRotation);
|
penpotNode = await transformGroupNode(node);
|
||||||
break;
|
break;
|
||||||
case 'TEXT':
|
case 'TEXT':
|
||||||
penpotNode = transformTextNode(node, baseRotation);
|
penpotNode = transformTextNode(node);
|
||||||
break;
|
break;
|
||||||
case 'VECTOR':
|
case 'VECTOR':
|
||||||
penpotNode = transformVectorNode(node, baseRotation);
|
penpotNode = transformVectorNode(node);
|
||||||
break;
|
break;
|
||||||
case 'LINE':
|
case 'LINE':
|
||||||
penpotNode = transformLineNode(node, baseRotation);
|
penpotNode = transformLineNode(node);
|
||||||
break;
|
break;
|
||||||
case 'STAR':
|
case 'STAR':
|
||||||
case 'POLYGON':
|
case 'POLYGON':
|
||||||
penpotNode = transformPathNode(node, baseRotation);
|
penpotNode = transformPathNode(node);
|
||||||
break;
|
break;
|
||||||
case 'BOOLEAN_OPERATION':
|
case 'BOOLEAN_OPERATION':
|
||||||
penpotNode = await transformBooleanNode(node, baseRotation);
|
penpotNode = await transformBooleanNode(node);
|
||||||
break;
|
break;
|
||||||
case 'COMPONENT':
|
case 'COMPONENT':
|
||||||
penpotNode = await transformComponentNode(node, baseRotation);
|
penpotNode = await transformComponentNode(node);
|
||||||
break;
|
break;
|
||||||
case 'INSTANCE':
|
case 'INSTANCE':
|
||||||
penpotNode = await transformInstanceNode(node, baseRotation);
|
penpotNode = await transformInstanceNode(node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ import {
|
||||||
|
|
||||||
import { TextShape } from '@ui/lib/types/shapes/textShape';
|
import { TextShape } from '@ui/lib/types/shapes/textShape';
|
||||||
|
|
||||||
export const transformTextNode = (node: TextNode, baseRotation: number): TextShape => {
|
export const transformTextNode = (node: TextNode): TextShape => {
|
||||||
return {
|
return {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: node.name,
|
name: node.name,
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...transformText(node),
|
...transformText(node),
|
||||||
...transformDimension(node),
|
...transformDimension(node),
|
||||||
...transformRotationAndPosition(node, baseRotation),
|
...transformRotationAndPosition(node),
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
|
|
|
@ -16,11 +16,8 @@ import { transformGroupNodeLike } from '.';
|
||||||
* If there are no regions on the vector network, we treat it like a normal `PathShape`.
|
* If there are no regions on the vector network, we treat it like a normal `PathShape`.
|
||||||
* If there are regions, we treat the vector node as a `GroupShape` with multiple `PathShape` children.
|
* If there are regions, we treat the vector node as a `GroupShape` with multiple `PathShape` children.
|
||||||
*/
|
*/
|
||||||
export const transformVectorNode = (
|
export const transformVectorNode = (node: VectorNode): GroupShape | PathShape => {
|
||||||
node: VectorNode,
|
const children = transformVectorPaths(node);
|
||||||
baseRotation: number
|
|
||||||
): GroupShape | PathShape => {
|
|
||||||
const children = transformVectorPaths(node, baseRotation);
|
|
||||||
|
|
||||||
if (children.length === 1) {
|
if (children.length === 1) {
|
||||||
return {
|
return {
|
||||||
|
@ -33,7 +30,7 @@ export const transformVectorNode = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...transformGroupNodeLike(node, baseRotation),
|
...transformGroupNodeLike(node),
|
||||||
...transformFigmaIds(node),
|
...transformFigmaIds(node),
|
||||||
...transformConstraints(node),
|
...transformConstraints(node),
|
||||||
...transformOverrides(node),
|
...transformOverrides(node),
|
||||||
|
|
|
@ -16,13 +16,12 @@ import { PenpotNode } from '@ui/types';
|
||||||
*/
|
*/
|
||||||
export const translateMaskChildren = async (
|
export const translateMaskChildren = async (
|
||||||
children: readonly SceneNode[],
|
children: readonly SceneNode[],
|
||||||
maskIndex: number,
|
maskIndex: number
|
||||||
baseRotation: number
|
|
||||||
): Promise<PenpotNode[]> => {
|
): Promise<PenpotNode[]> => {
|
||||||
const maskChild = children[maskIndex];
|
const maskChild = children[maskIndex];
|
||||||
|
|
||||||
const unmaskedChildren = await translateChildren(children.slice(0, maskIndex), baseRotation);
|
const unmaskedChildren = await translateChildren(children.slice(0, maskIndex));
|
||||||
const maskedChildren = await translateChildren(children.slice(maskIndex), baseRotation);
|
const maskedChildren = await translateChildren(children.slice(maskIndex));
|
||||||
|
|
||||||
if (
|
if (
|
||||||
maskChild.type === 'STICKY' ||
|
maskChild.type === 'STICKY' ||
|
||||||
|
@ -41,7 +40,7 @@ export const translateMaskChildren = async (
|
||||||
|
|
||||||
const maskGroup = {
|
const maskGroup = {
|
||||||
...transformMaskFigmaIds(maskChild),
|
...transformMaskFigmaIds(maskChild),
|
||||||
...transformGroupNodeLike(maskChild, baseRotation),
|
...transformGroupNodeLike(maskChild),
|
||||||
children: maskedChildren,
|
children: maskedChildren,
|
||||||
maskedGroup: true
|
maskedGroup: true
|
||||||
};
|
};
|
||||||
|
@ -49,14 +48,11 @@ export const translateMaskChildren = async (
|
||||||
return [...unmaskedChildren, maskGroup];
|
return [...unmaskedChildren, maskGroup];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const translateChildren = async (
|
export const translateChildren = async (children: readonly SceneNode[]): Promise<PenpotNode[]> => {
|
||||||
children: readonly SceneNode[],
|
|
||||||
baseRotation: number = 0
|
|
||||||
): Promise<PenpotNode[]> => {
|
|
||||||
const transformedChildren: PenpotNode[] = [];
|
const transformedChildren: PenpotNode[] = [];
|
||||||
|
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
const penpotNode = await transformSceneNode(child, baseRotation);
|
const penpotNode = await transformSceneNode(child);
|
||||||
|
|
||||||
if (penpotNode) transformedChildren.push(penpotNode);
|
if (penpotNode) transformedChildren.push(penpotNode);
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,27 @@ import { ShapeBaseAttributes } from '@ui/lib/types/shapes/shape';
|
||||||
export const translateRotation = (
|
export const translateRotation = (
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
rotation: number
|
rotation: number
|
||||||
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => ({
|
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => {
|
||||||
rotation: -rotation < 0 ? -rotation + 360 : -rotation,
|
return {
|
||||||
transform: {
|
rotation,
|
||||||
a: transform[0][0],
|
transform: {
|
||||||
b: transform[1][0],
|
a: transform[0][0],
|
||||||
c: transform[0][1],
|
b: transform[1][0],
|
||||||
d: transform[1][1],
|
c: transform[0][1],
|
||||||
e: 0,
|
d: transform[1][1],
|
||||||
f: 0
|
e: 0,
|
||||||
},
|
f: 0
|
||||||
transformInverse: {
|
},
|
||||||
a: transform[0][0],
|
transformInverse: {
|
||||||
b: transform[0][1],
|
a: transform[0][0],
|
||||||
c: transform[1][0],
|
b: transform[0][1],
|
||||||
d: transform[1][1],
|
c: transform[1][0],
|
||||||
e: 0,
|
d: transform[1][1],
|
||||||
f: 0
|
e: 0,
|
||||||
}
|
f: 0
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const translateZeroRotation = (): Pick<
|
export const translateZeroRotation = (): Pick<
|
||||||
ShapeBaseAttributes,
|
ShapeBaseAttributes,
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { Command } from 'svg-path-parser';
|
import { Command } from 'svg-path-parser';
|
||||||
|
|
||||||
import { hasRotation } from '@plugin/utils';
|
import { getRotation, hasRotation } from '@plugin/utils';
|
||||||
|
|
||||||
import { translateNonRotatedCommands } from '.';
|
import { translateNonRotatedCommands } from '.';
|
||||||
import { translateRotatedCommands } from './translateRotatedCommands';
|
import { translateRotatedCommands } from './translateRotatedCommands';
|
||||||
|
|
||||||
export const translateCommands = (node: LayoutMixin, commands: Command[], baseRotation: number) => {
|
export const translateCommands = (node: LayoutMixin, commands: Command[]) => {
|
||||||
if (hasRotation(node.rotation + baseRotation) && node.absoluteBoundingBox) {
|
const rotation = getRotation(node.absoluteTransform);
|
||||||
|
|
||||||
|
if (hasRotation(rotation) && node.absoluteBoundingBox) {
|
||||||
return translateRotatedCommands(commands, node.absoluteTransform, node.absoluteBoundingBox);
|
return translateRotatedCommands(commands, node.absoluteTransform, node.absoluteBoundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,10 @@ export const applyInverseRotation = (
|
||||||
boundingBox: Rect
|
boundingBox: Rect
|
||||||
): Point => applyRotation(point, inverseMatrix(transform), boundingBox);
|
): Point => applyRotation(point, inverseMatrix(transform), boundingBox);
|
||||||
|
|
||||||
export const hasRotation = (rotation: number): boolean => Math.abs(rotation) > ROTATION_TOLERANCE;
|
export const getRotation = (transform: Transform): number =>
|
||||||
|
Math.acos(transform[0][0]) * (180 / Math.PI);
|
||||||
|
|
||||||
|
export const hasRotation = (rotation: number): boolean => rotation > ROTATION_TOLERANCE;
|
||||||
|
|
||||||
const inverseMatrix = (matrix: Transform): Transform => [
|
const inverseMatrix = (matrix: Transform): Transform => [
|
||||||
[matrix[0][0], matrix[1][0], matrix[0][2]],
|
[matrix[0][0], matrix[1][0], matrix[0][2]],
|
||||||
|
|
Loading…
Reference in a new issue