mirror of
https://github.com/motion-canvas/motion-canvas.git
synced 2026-01-11 23:07:57 -05:00
feat: add LayoutText
This commit is contained in:
@@ -2,7 +2,9 @@ import {Size, Origin, Direction} from '../types';
|
||||
import {Node} from 'konva/lib/Node';
|
||||
import {LayoutGroup} from 'MC/components/LayoutGroup';
|
||||
import {LayoutShape} from 'MC/components/LayoutShape';
|
||||
import {Vector2d} from 'konva/lib/types';
|
||||
import {IRect, Vector2d} from 'konva/lib/types';
|
||||
import {Shape} from "konva/lib/Shape";
|
||||
import {Group} from "konva/lib/Group";
|
||||
|
||||
export const LAYOUT_CHANGE_EVENT = 'layoutChange';
|
||||
|
||||
@@ -20,7 +22,15 @@ export interface ILayoutNode {
|
||||
getPadding(): number;
|
||||
getColor(): string;
|
||||
getOrigin(): Origin;
|
||||
getLayoutSize(): Size;
|
||||
getOriginOffset(custom?: Partial<LayoutAttrs>): Vector2d;
|
||||
getOriginDelta(newOrigin: Origin, custom?: Partial<LayoutAttrs>): Vector2d;
|
||||
getLayoutSize(custom?: Partial<LayoutAttrs>): Size;
|
||||
}
|
||||
|
||||
export type LayoutNode = (Shape | Group) & ILayoutNode;
|
||||
|
||||
export function isLayoutNode(node: Node): node is LayoutNode {
|
||||
return 'getLayoutSize' in node;
|
||||
}
|
||||
|
||||
export function isInsideLayout(node: Node) {
|
||||
@@ -76,3 +86,29 @@ export function getOriginDelta(size: Size, from: Origin, to: Origin) {
|
||||
y: toOffset.y - fromOffset.y,
|
||||
};
|
||||
}
|
||||
|
||||
export function getClientRect(
|
||||
node: LayoutNode,
|
||||
config?: {
|
||||
skipTransform?: boolean;
|
||||
skipShadow?: boolean;
|
||||
skipStroke?: boolean;
|
||||
relativeTo?: Node;
|
||||
},
|
||||
): IRect {
|
||||
const size = node.getLayoutSize();
|
||||
const offset = node.getOriginOffset({origin: Origin.TopLeft});
|
||||
|
||||
const rect: IRect = {
|
||||
x: offset.x,
|
||||
y: offset.y,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
};
|
||||
|
||||
if (!config?.skipTransform) {
|
||||
return node._transformedRect(rect, config?.relativeTo);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import {Group} from 'konva/lib/Group';
|
||||
import {Container, ContainerConfig} from 'konva/lib/Container';
|
||||
import {Origin, Size} from '../types';
|
||||
import {
|
||||
getClientRect,
|
||||
getOriginDelta,
|
||||
getOriginOffset,
|
||||
ILayoutNode,
|
||||
@@ -12,12 +13,17 @@ import {
|
||||
import Konva from 'konva';
|
||||
import {IRect} from 'konva/lib/types';
|
||||
import Vector2d = Konva.Vector2d;
|
||||
import {Project} from '../Project';
|
||||
|
||||
export type LayoutGroupConfig = Partial<LayoutAttrs> & ContainerConfig;
|
||||
|
||||
export abstract class LayoutGroup extends Group implements ILayoutNode {
|
||||
public attrs: LayoutGroupConfig;
|
||||
|
||||
public get project(): Project {
|
||||
return <Project>this.getStage();
|
||||
}
|
||||
|
||||
public constructor(config?: LayoutGroupConfig) {
|
||||
super({
|
||||
color: '#242424',
|
||||
@@ -28,7 +34,7 @@ export abstract class LayoutGroup extends Group implements ILayoutNode {
|
||||
this.handleLayoutChange();
|
||||
}
|
||||
|
||||
public abstract getLayoutSize(): Size;
|
||||
public abstract getLayoutSize(custom?: LayoutGroupConfig): Size;
|
||||
|
||||
public setRadius(value: number): this {
|
||||
this.attrs.radius = value;
|
||||
@@ -88,15 +94,19 @@ export abstract class LayoutGroup extends Group implements ILayoutNode {
|
||||
this.setOrigin(previousOrigin);
|
||||
}
|
||||
|
||||
public getOriginOffset(customOrigin?: Origin): Vector2d {
|
||||
public getOriginOffset(custom?: LayoutGroupConfig): Vector2d {
|
||||
return getOriginOffset(
|
||||
this.getLayoutSize(),
|
||||
customOrigin ?? this.getOrigin(),
|
||||
this.getLayoutSize(custom),
|
||||
custom?.origin ?? this.getOrigin(),
|
||||
);
|
||||
}
|
||||
|
||||
public getOriginDelta(newOrigin: Origin) {
|
||||
return getOriginDelta(this.getLayoutSize(), this.getOrigin(), newOrigin);
|
||||
public getOriginDelta(newOrigin: Origin, custom?: LayoutGroupConfig) {
|
||||
return getOriginDelta(
|
||||
this.getLayoutSize(custom),
|
||||
custom?.origin ?? this.getOrigin(),
|
||||
newOrigin,
|
||||
);
|
||||
}
|
||||
|
||||
public getClientRect(config?: {
|
||||
@@ -105,21 +115,7 @@ export abstract class LayoutGroup extends Group implements ILayoutNode {
|
||||
skipStroke?: boolean;
|
||||
relativeTo?: Container;
|
||||
}): IRect {
|
||||
const size = this.getLayoutSize();
|
||||
const offset = this.getOriginOffset(Origin.TopLeft);
|
||||
|
||||
const rect: IRect = {
|
||||
x: offset.x,
|
||||
y: offset.y,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
};
|
||||
|
||||
if (!config?.skipTransform) {
|
||||
return this._transformedRect(rect, config?.relativeTo);
|
||||
}
|
||||
|
||||
return rect;
|
||||
return getClientRect(this, config);
|
||||
}
|
||||
|
||||
protected fireLayoutChange() {
|
||||
|
||||
@@ -8,22 +8,28 @@ import {
|
||||
isInsideLayout,
|
||||
LAYOUT_CHANGE_EVENT,
|
||||
LayoutAttrs,
|
||||
getClientRect,
|
||||
} from './ILayoutNode';
|
||||
import {Size} from '../types';
|
||||
import {IRect, Vector2d} from 'konva/lib/types';
|
||||
import {Project} from "../Project";
|
||||
|
||||
export type LayoutShapeConfig = Partial<LayoutAttrs> & ShapeConfig;
|
||||
|
||||
export abstract class LayoutShape extends Shape implements ILayoutNode {
|
||||
public attrs: LayoutShapeConfig;
|
||||
|
||||
public get project(): Project {
|
||||
return <Project>this.getStage();
|
||||
}
|
||||
|
||||
public constructor(config?: LayoutShapeConfig) {
|
||||
super(config);
|
||||
this.on(LAYOUT_CHANGE_EVENT, () => this.handleLayoutChange());
|
||||
this.handleLayoutChange();
|
||||
}
|
||||
|
||||
public abstract getLayoutSize(): Size;
|
||||
public abstract getLayoutSize(custom?: LayoutShapeConfig): Size;
|
||||
|
||||
public setRadius(value: number): this {
|
||||
this.attrs.radius = value;
|
||||
@@ -83,15 +89,19 @@ export abstract class LayoutShape extends Shape implements ILayoutNode {
|
||||
this.setOrigin(previousOrigin);
|
||||
}
|
||||
|
||||
public getOriginOffset(customOrigin?: Origin): Vector2d {
|
||||
public getOriginOffset(custom?: LayoutShapeConfig): Vector2d {
|
||||
return getOriginOffset(
|
||||
this.getLayoutSize(),
|
||||
customOrigin ?? this.getOrigin(),
|
||||
this.getLayoutSize(custom),
|
||||
custom?.origin ?? this.getOrigin(),
|
||||
);
|
||||
}
|
||||
|
||||
public getOriginDelta(newOrigin: Origin) {
|
||||
return getOriginDelta(this.getLayoutSize(), this.getOrigin(), newOrigin);
|
||||
public getOriginDelta(newOrigin: Origin, custom?: LayoutShapeConfig) {
|
||||
return getOriginDelta(
|
||||
this.getLayoutSize(custom),
|
||||
custom?.origin ?? this.getOrigin(),
|
||||
newOrigin,
|
||||
);
|
||||
}
|
||||
|
||||
public getClientRect(config?: {
|
||||
@@ -100,21 +110,7 @@ export abstract class LayoutShape extends Shape implements ILayoutNode {
|
||||
skipStroke?: boolean;
|
||||
relativeTo?: Container;
|
||||
}): IRect {
|
||||
const size = this.getLayoutSize();
|
||||
const offset = this.getOriginOffset(Origin.TopLeft);
|
||||
|
||||
const rect: IRect = {
|
||||
x: offset.x,
|
||||
y: offset.y,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
};
|
||||
|
||||
if (!config?.skipTransform) {
|
||||
return this._transformedRect(rect, config?.relativeTo);
|
||||
}
|
||||
|
||||
return rect;
|
||||
return getClientRect(this, config);
|
||||
}
|
||||
|
||||
protected fireLayoutChange() {
|
||||
|
||||
188
src/components/LayoutText.ts
Normal file
188
src/components/LayoutText.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
import {Text, TextConfig} from 'konva/lib/shapes/Text';
|
||||
import {IRect, Vector2d} from 'konva/lib/types';
|
||||
import {ShapeGetClientRectConfig} from 'konva/lib/Shape';
|
||||
import {
|
||||
getOriginDelta,
|
||||
getOriginOffset,
|
||||
ILayoutNode,
|
||||
isInsideLayout,
|
||||
LAYOUT_CHANGE_EVENT,
|
||||
LayoutAttrs,
|
||||
} from './ILayoutNode';
|
||||
import {Project} from '../Project';
|
||||
import {Origin, Size} from '../types';
|
||||
|
||||
export interface LayoutTextConfig extends Partial<LayoutAttrs>, TextConfig {
|
||||
minWidth?: number;
|
||||
}
|
||||
|
||||
export class LayoutText extends Text implements ILayoutNode {
|
||||
public get project(): Project {
|
||||
return <Project>this.getStage();
|
||||
}
|
||||
|
||||
private overrideWidth: number | null = null;
|
||||
private isConstructed = false;
|
||||
|
||||
public constructor(config?: LayoutTextConfig) {
|
||||
super({
|
||||
color: '#c0b3a3',
|
||||
radius: 40,
|
||||
padding: 30,
|
||||
align: 'center',
|
||||
verticalAlign: 'middle',
|
||||
height: 20,
|
||||
fontSize: 28,
|
||||
fontFamily: 'JetBrains Mono',
|
||||
fill: 'rgba(30, 30, 30, 0.87)',
|
||||
...config,
|
||||
});
|
||||
this.isConstructed = true;
|
||||
this.on(LAYOUT_CHANGE_EVENT, () => this.handleLayoutChange());
|
||||
this.handleLayoutChange();
|
||||
this.offset(this.getOriginOffset());
|
||||
}
|
||||
|
||||
public getLayoutSize(custom?: LayoutTextConfig): Size {
|
||||
const size = this.measureSize(custom?.text ?? this.text());
|
||||
return {
|
||||
width: Math.max(
|
||||
custom?.minWidth ?? this.getMinWidth(),
|
||||
this.overrideWidth ?? (size.width + this.getPadding() * 2),
|
||||
),
|
||||
height: (this.isConstructed ? this.getHeight() : 0) + this.getPadding() * 2,
|
||||
};
|
||||
}
|
||||
|
||||
public setRadius(value: number): this {
|
||||
this.attrs.radius = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public getRadius(): number {
|
||||
return this.attrs.radius ?? 0;
|
||||
}
|
||||
|
||||
public setMargin(value: number): this {
|
||||
this.attrs.margin = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public getMargin(): Origin {
|
||||
return this.attrs.margin ?? 0;
|
||||
}
|
||||
|
||||
public setPadding(value: number): this {
|
||||
this.attrs.padding = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public getPadding(): number {
|
||||
return this.attrs.padding ?? 0;
|
||||
}
|
||||
|
||||
public setColor(value: string): this {
|
||||
this.attrs.color = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public getColor(): string {
|
||||
return this.attrs.color ?? '#000';
|
||||
}
|
||||
|
||||
public setMinWidth(value: number): this {
|
||||
this.attrs.minWidth = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public getMinWidth(): number {
|
||||
return this.attrs.minWidth ?? 0;
|
||||
}
|
||||
|
||||
setText(text: string): this {
|
||||
super.setText(text);
|
||||
this.offset(this.getOriginOffset());
|
||||
this.fireLayoutChange();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public setOrigin(value: Origin): this {
|
||||
if (!isInsideLayout(this)) {
|
||||
this.move(this.getOriginDelta(value));
|
||||
}
|
||||
this.attrs.origin = value;
|
||||
this.offset(this.getOriginOffset());
|
||||
this.fireLayoutChange();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public getOrigin(): Origin {
|
||||
return this.attrs.origin ?? Origin.Middle;
|
||||
}
|
||||
|
||||
public withOrigin(origin: Origin, action: () => void) {
|
||||
const previousOrigin = this.getOrigin();
|
||||
this.setOrigin(origin);
|
||||
action();
|
||||
this.setOrigin(previousOrigin);
|
||||
}
|
||||
|
||||
public getOriginOffset(custom?: LayoutTextConfig): Vector2d {
|
||||
const size = this.getLayoutSize({minWidth: 0, ...custom});
|
||||
const offset = getOriginOffset(size, custom?.origin ?? this.getOrigin());
|
||||
offset.x += size.width / 2;
|
||||
offset.y += size.height / 2 - this.getPadding();
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
public *animate(text: string) {
|
||||
const fromText = this.text();
|
||||
const fromWidth = this.getLayoutSize({minWidth: 0}).width;
|
||||
const toWidth = this.getLayoutSize({text, minWidth: 0}).width;
|
||||
|
||||
this.overrideWidth = fromWidth;
|
||||
yield* this.project.tween(3, value => {
|
||||
this.overrideWidth = value.easeInOutCubic(fromWidth, toWidth);
|
||||
this.setText(value.text(fromText, text, value.easeInOutCubic()));
|
||||
});
|
||||
this.overrideWidth = null;
|
||||
|
||||
this.setText(text);
|
||||
}
|
||||
|
||||
public getOriginDelta(newOrigin: Origin, custom?: LayoutTextConfig) {
|
||||
return getOriginDelta(
|
||||
this.getLayoutSize(custom),
|
||||
custom?.origin ?? this.getOrigin(),
|
||||
newOrigin,
|
||||
);
|
||||
}
|
||||
|
||||
public getClientRect(config?: ShapeGetClientRectConfig): IRect {
|
||||
const realSize = this.getLayoutSize({minWidth: 0});
|
||||
const size = this.getLayoutSize();
|
||||
const offset = this.getOriginOffset({origin: Origin.TopLeft});
|
||||
|
||||
const rect: IRect = {
|
||||
x: offset.x + (realSize.width - size.width) / 2,
|
||||
y: offset.y,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
};
|
||||
|
||||
if (!config?.skipTransform) {
|
||||
return this._transformedRect(rect, config?.relativeTo);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
protected fireLayoutChange() {
|
||||
this.getParent()?.fire(LAYOUT_CHANGE_EVENT, undefined, true);
|
||||
}
|
||||
|
||||
protected handleLayoutChange() {}
|
||||
}
|
||||
@@ -5,9 +5,8 @@ import {Shape} from 'konva/lib/Shape';
|
||||
import {parseColor} from 'mix-color';
|
||||
import {Project} from '../Project';
|
||||
import {LayoutGroup} from './LayoutGroup';
|
||||
import {LayoutShape} from './LayoutShape';
|
||||
import {Origin, Size} from '../types';
|
||||
import {getOriginDelta, getOriginOffset, LayoutAttrs} from './ILayoutNode';
|
||||
import {getOriginDelta, getOriginOffset, isLayoutNode, LayoutAttrs, LayoutNode} from './ILayoutNode';
|
||||
import {CanvasHelper} from "../helpers";
|
||||
|
||||
export type LayoutData = LayoutAttrs & Size;
|
||||
@@ -25,7 +24,7 @@ export interface SurfaceConfig extends ContainerConfig {
|
||||
export class Surface extends LayoutGroup {
|
||||
private box: Rect;
|
||||
private ripple: Rect;
|
||||
private child: LayoutGroup | LayoutShape;
|
||||
private child: LayoutNode;
|
||||
private override: boolean = false;
|
||||
private mask: SurfaceMask = null;
|
||||
private layoutData: LayoutData;
|
||||
@@ -65,10 +64,7 @@ export class Surface extends LayoutGroup {
|
||||
|
||||
add(...children: (Shape | Group)[]): this {
|
||||
super.add(...children);
|
||||
const child = children.find<LayoutShape | LayoutGroup>(
|
||||
(child): child is LayoutShape | LayoutGroup =>
|
||||
child instanceof LayoutShape || child instanceof LayoutGroup,
|
||||
);
|
||||
const child = children.find<LayoutNode>(isLayoutNode);
|
||||
const ripple = children.find<Rect>((child): child is Rect =>
|
||||
child.hasName('ripple'),
|
||||
);
|
||||
@@ -131,7 +127,7 @@ export class Surface extends LayoutGroup {
|
||||
this.ripple.hide();
|
||||
}
|
||||
|
||||
public getChild(): LayoutShape | LayoutGroup {
|
||||
public getChild(): LayoutNode {
|
||||
return this.child;
|
||||
}
|
||||
|
||||
@@ -192,11 +188,12 @@ export class Surface extends LayoutGroup {
|
||||
const size = this.child.getLayoutSize();
|
||||
const margin = this.child.getMargin();
|
||||
const scale = this.child.getAbsoluteScale(this);
|
||||
const padding = this.getPadding();
|
||||
|
||||
this.layoutData = {
|
||||
...this.layoutData,
|
||||
width: (size.width + margin * 2) * scale.x,
|
||||
height: (size.height + margin * 2) * scale.y,
|
||||
width: (size.width + margin * 2 + padding * 2) * scale.x,
|
||||
height: (size.height + margin * 2 + padding * 2) * scale.y,
|
||||
radius: this.child.getRadius(),
|
||||
color: this.child.getColor(),
|
||||
};
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
import {Text} from 'konva/lib/shapes/Text';
|
||||
import {GetSet, Vector2d} from 'konva/lib/types';
|
||||
import {Shape} from 'konva/lib/Shape';
|
||||
import {Factory} from 'konva/lib/Factory';
|
||||
import {getNumberValidator} from 'konva/lib/Validators';
|
||||
import {Project} from '../Project';
|
||||
import {LayoutGroup, LayoutGroupConfig} from './LayoutGroup';
|
||||
import {Group} from 'konva/lib/Group';
|
||||
import {Size} from '../types';
|
||||
|
||||
export interface TextContentConfig extends LayoutGroupConfig {
|
||||
minWidth?: number;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export class TextContent extends LayoutGroup {
|
||||
public minWidth: GetSet<number, this>;
|
||||
|
||||
private text: Text;
|
||||
|
||||
public get project(): Project {
|
||||
return <Project>this.getStage();
|
||||
}
|
||||
|
||||
public constructor(config?: TextContentConfig) {
|
||||
super({
|
||||
color: '#c0b3a3',
|
||||
radius: 40,
|
||||
height: 80,
|
||||
...config,
|
||||
});
|
||||
this.add(
|
||||
new Text({
|
||||
name: 'text',
|
||||
height: 80,
|
||||
fontSize: 28,
|
||||
text: config.text,
|
||||
verticalAlign: 'middle',
|
||||
fontFamily: 'JetBrains Mono',
|
||||
fill: 'rgba(30, 30, 30, 0.87)',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
add(...children: (Shape | Group)[]): this {
|
||||
super.add(...children);
|
||||
const text = children.find<Text>((child): child is Text =>
|
||||
child.hasName('text'),
|
||||
);
|
||||
|
||||
if (text) {
|
||||
this.text?.destroy();
|
||||
this.text = text;
|
||||
this.text?.text(this.getText());
|
||||
this.handleLayoutChange();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
getLayoutSize(): Size {
|
||||
return this.getSize();
|
||||
}
|
||||
|
||||
public setText(value: string): this {
|
||||
this.text?.setText(value);
|
||||
this.attrs.text = value;
|
||||
this.handleLayoutChange();
|
||||
return this;
|
||||
}
|
||||
|
||||
public getText(): string {
|
||||
return this.attrs.text ?? '';
|
||||
}
|
||||
|
||||
public *animateText(text: string) {
|
||||
const fromText = this.text.text();
|
||||
const from = this.recalculateValues(fromText);
|
||||
const to = this.recalculateValues(text);
|
||||
|
||||
yield* this.project.tween(0.3, value => {
|
||||
this.text.setText(value.text(fromText, text, value.easeInOutCubic()));
|
||||
this.width(value.easeInOutCubic(from.width, to.width));
|
||||
this.text.offset(
|
||||
value.vector2d(from.offset, to.offset, value.easeInOutCubic()),
|
||||
);
|
||||
this.fireLayoutChange();
|
||||
});
|
||||
|
||||
this.setText(text);
|
||||
}
|
||||
|
||||
protected handleLayoutChange() {
|
||||
if (!this.text) return;
|
||||
|
||||
const values = this.recalculateValues(this.text.text());
|
||||
this.text.offset(values.offset);
|
||||
this.width(values.width);
|
||||
this.fireLayoutChange();
|
||||
}
|
||||
|
||||
private recalculateValues(text: string) {
|
||||
const minWidth = this.minWidth();
|
||||
const size = this.text.measureSize(text);
|
||||
const textWidth = Math.max(minWidth, size.width);
|
||||
const boxWidth = Math.ceil((textWidth + 80) / 20) * 20;
|
||||
|
||||
return {
|
||||
width: boxWidth,
|
||||
offset: <Vector2d>{x: size.width / 2, y: 38},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Factory.addGetterSetter(
|
||||
TextContent,
|
||||
'minWidth',
|
||||
0,
|
||||
getNumberValidator(),
|
||||
// @ts-ignore
|
||||
TextContent.prototype.recalculate,
|
||||
);
|
||||
@@ -4,5 +4,4 @@ export * from './Debug';
|
||||
export * from './Layout';
|
||||
export * from './Sprite';
|
||||
export * from './Surface';
|
||||
export * from './TextContent';
|
||||
export * from './ThreeView';
|
||||
@@ -21,3 +21,28 @@ export enum Origin {
|
||||
BottomLeft = 24,
|
||||
BottomRight = 40,
|
||||
}
|
||||
|
||||
export function flipOrigin(origin: Direction, axis?: Center): Direction;
|
||||
export function flipOrigin(origin: Origin, axis?: Center): Origin;
|
||||
export function flipOrigin(
|
||||
origin: Origin | Direction,
|
||||
axis: Center = Center.Horizontal | Center.Vertical,
|
||||
): Origin | Direction {
|
||||
if (axis & Center.Vertical) {
|
||||
if (origin & Direction.Top) {
|
||||
origin = (origin & ~Direction.Top) | Direction.Bottom;
|
||||
} else if (origin & Direction.Bottom) {
|
||||
origin = (origin & ~Direction.Bottom) | Direction.Top;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis & Center.Horizontal) {
|
||||
if (origin & Direction.Left) {
|
||||
origin = (origin & ~Direction.Left) | Direction.Right;
|
||||
} else if (origin & Direction.Right) {
|
||||
origin = (origin & ~Direction.Right) | Direction.Left;
|
||||
}
|
||||
}
|
||||
|
||||
return origin;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user