import type { AxisAlignedBounds } from '@pixi-essentials/bounds'; import { Container } from '@pixi/display'; import { DisplayObject } from '@pixi/display'; import { FederatedEventTarget } from '@pixi/events'; import { FederatedPointerEvent } from '@pixi/events'; import { Graphics } from '@pixi/graphics'; import { IFederatedDisplayObject } from '@pixi/events'; import { Matrix } from '@pixi/math'; import { OrientedBounds } from '@pixi-essentials/bounds'; import { Point } from '@pixi/math'; import { Renderer } from '@pixi/core'; import { utils } from '@pixi/core'; declare const Container_: new () => Container & IFederatedDisplayObject & Omit & utils.EventEmitter; declare const Graphics_: new () => Graphics & FederatedEventTarget; declare const Graphics__2: new () => Graphics & FederatedEventTarget; declare type GraphicsT_ = Graphics & FederatedEventTarget; /** * All the handles provided by {@link Transformer}. * * @public * @ignore */ export declare type Handle = RotateHandle | ScaleHandle | SkewHandle; /** * @public */ export declare interface ITransformerCursors { default: string; boxRotate?: string; boxScaleLeft?: string; boxScaleTop?: string; boxScaleRight?: string; boxScaleBottom?: string; translate?: string; } /** @see TransformerHandle#style */ export declare interface ITransformerHandleStyle { /** Fill color of the handle */ color: number; /** Outline color of the handle */ outlineColor: number; /** Outline thickness around the handle */ outlineThickness: number; /** Radius (or size for non-circular handles) of the handle */ radius: number; /** {@link TransformerHandle} provides three types of handle shapes - 'circle', 'square', 'tooth'. */ shape: string; } /** * @public */ export declare interface ITransformerOptions { /** "all" or "groupOnly". "groupOnly" won't show individual bounding boxes. */ boundingBoxes?: 'all' | 'groupOnly' | 'none'; /** Enable box rotation by dragging outside of corners */ boxRotationEnabled?: boolean; /** The radial tolerance for box rotation */ boxRotationTolerance?: number; /** Enable box scaling by dragging at the edges */ boxScalingEnabled?: boolean; /** The tolerance for scaling at the edges */ boxScalingTolerance: number; /** Whether scaling should always be centered */ centeredScaling: boolean; /** */ cursors?: ITransformerCursors; /** Specifically define which handles are to be enabled */ enabledHandles?: Array; /** The group of display-objects being transformed */ group: DisplayObject[]; /** A custom transformer-handle class */ handleConstructor: typeof TransformerHandle; /** Styling options for the handle. These cannot be modified afterwards! */ handleStyle: Partial; /** Lock aspect ratio when scaling using one of the corner handles. */ lockAspectRatio?: boolean; /** Whether rotate handles are enabled */ rotateEnabled?: boolean; /** * The rotation snap angles, in radians. By default, transformer will * snap for each 1/8th of a revolution. */ rotationSnaps?: number[]; /** The snap tolerance for rotation in radians */ rotationSnapTolerance?: number; /** Whether scale handles are enabled */ scaleEnabled?: boolean; /** Whether skew handles are enabled */ skewEnabled?: boolean; /** * Distance of skew handles from center of transformer box * (`skewTransform` should be enabled) */ skewRadius?: number; /** The skew snap angles, in radians. */ skewSnaps?: number[]; /** The skew snap tolerance angle. */ skewSnapTolerance?: number; /** The root object in your scene in which the transformed objects exist. */ stage: Container; /** Whether dragging the transformer should move the group */ translateEnabled?: boolean; /** * Whether the transformer should reset the wireframe's rotation * after a rotator handle is "defocused". */ transientGroupTilt?: boolean; /** Styling options for the wireframe. */ wireframeStyle: Partial; } /** * @ignore */ export declare interface ITransformerStyle { color: number; thickness: number; } /** * The handles used for rotation. * * @public * @ignore */ export declare type RotateHandle = 'rotator' | 'boxRotateTopLeft' | 'boxRotateTopRight' | 'boxRotateBottomLeft' | 'boxRotateBottomRight'; /** * The handles used for scaling. * * @public * @ignore */ export declare type ScaleHandle = 'topLeft' | 'topCenter' | 'topRight' | 'middleLeft' | 'middleCenter' | 'middleRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight'; /** * The handles used for skewing * * @public * @ignore */ export declare type SkewHandle = 'skewHorizontal' | 'skewVertical'; /** * {@code Transformer} provides an interactive interface for editing the transforms in a group. It supports translating, * scaling, rotating, and skewing display-objects both through interaction and code. * * A transformer operates in world-space, and it is best to not position, scale, rotate, or skew one. If you do so, the * wireframe itself will not distort (i.e. will adapt _against_ your transforms). However, the wireframe may become * thinner/thicker and the handles will scale & rotate. For example, setting `transformer.scale.set(2)` will make the handles * twice as big, but will not scale the wireframe (assuming the display-object group itself has not been * scaled up). * * To enable scaling via dragging the edges of the wireframe, set `boxScalingEnabled` to `true`. * * NOTE: The transformer needs to capture all interaction events that would otherwise go to the display-objects in the * group. Hence, it must be placed after them in the scene graph. * * @extends PIXI.Container */ declare class Transformer_2 extends Container_ { /** The group of display-objects under transformation. */ group: DisplayObject[]; /** * Specify which bounding boxes should be drawn in the wireframe. * * "groupOnly" won't show individual bounding boxes. "none" will not render anything visible. * * @default "all" */ boundingBoxes: 'all' | 'groupOnly' | 'none'; /** Set this to enable rotation at the four corners */ boxRotationEnabled: boolean; /** The thickness of the box rotation area */ boxRotationTolerance: number; /** Set this to enable scaling by dragging at the edges of the bounding box */ boxScalingEnabled: boolean; /** The padding around the bounding-box to capture dragging on the edges. */ boxScalingTolerance: number; /** This will prevent the wireframe's center from shifting on scaling. */ centeredScaling: boolean; /** Cursors to use in the transformer */ cursors: ITransformerCursors; /** * Flags whether the transformer should **not** redraw each frame (good for performance) * * @default false */ lazyMode: boolean; /** Set this when you want the transformer to redraw when using {@link Transformer#lazyMode lazyMode}. */ lazyDirty: boolean; /** Lock aspect ratio when using one of the corner handles. */ lockAspectRatio: boolean; /** * This is used when the display-object group are rendered through a projection transformation (i.e. are disconnected * from the transformer in the scene graph). The transformer project itself into their frame-of-reference using this * transform. * * Specifically, the projection-transform converts points from the group's world space to the transformer's world * space. If you are not applying a projection on the transformer itself, this means it is the group's * world-to-screen transformation. */ projectionTransform: Matrix; /** The angles at which rotation should snap. */ rotationSnaps: number[]; /** The maximum angular difference for snapping rotation. */ rotationSnapTolerance: number; /** The distance of skewing handles from the group's center. */ skewRadius: number; /** The angles at which both the horizontal & vertical skew handles should snap. */ skewSnaps: number[]; /** * The maximum angular difference for snapping skew handles. */ skewSnapTolerance: number; /** * The root object in your scene in which objects can move. * * {@code Transformer} will subscribe to this object for `pointermove` events, if provided. This * should be used when: * * * {@link InteractionManager.moveWhenInside moveWhenInside} is enabled on the interaction plugin. * * {@link EventBoundary.moveOnAll moveOnAll} is not turned off when using the new {@link EventSystem}. * * Otherwise, the transformer will receive **not** `pointermove` events when the user drags fast enough that * the cursor leaves the transformer's bounds. * * The stage must be fully interactive in the area you want objects to move. Generally, this is the * whole canvas: * * ```ts * stage.interactive = true; * stage.hitArea = renderer.screen;// or pass custom rect for the canvas dimensions * ``` */ stage: Container | null; /** * This will enable translation on dragging the transformer. By default, it is turned on. * * @default true */ translateEnabled: boolean; /** * This will reset the rotation angle after the user finishes rotating a group with more than one display-object. * * @default true */ transientGroupTilt: boolean; /** The last calculated bounds of the whole group being transformed */ protected groupBounds: OrientedBounds; /** Object mapping handle-names to the handle display-objects. */ protected handles: { [H in Handle]?: TransformerHandle; }; /** * Positions of the various handles * * @internal * @ignore */ handleAnchors: { [H in Handle]: Point; }; /** Draws the bounding boxes */ protected wireframe: TransformerWireframe; /** @see Transformer#enabledHandles */ protected _enabledHandles: Handle[]; /** @see Transformer#rotateEnabled */ protected _rotateEnabled: boolean; /** @see Transformer#scaleEnabled */ protected _scaleEnabled: boolean; /** @see Transformer#skewEnabled */ protected _skewEnabled: boolean; /** The horizontal skew value. Rotating the group by 𝜽 will also change this value by 𝜽. */ protected _skewX: number; /** The vertical skew value. Rotating the group by 𝜽 will also change this value by 𝜽. */ protected _skewY: number; /** The currently grabbed handle. This can be used to get the type of transformation. */ protected _transformHandle: Handle; /** The current type of transform being applied by the user. */ protected _transformType: 'translate' | 'scale' | 'rotate' | 'skew' | 'none'; /** The style applied on transformer handles */ protected _handleStyle: Partial; /** The wireframe style applied on the transformer */ protected _wireframeStyle: Partial; private _pointerDown; private _pointerDragging; private _pointerPosition; private _pointerMoveTarget; /** * | Handle | Type | Notes | * | --------------------- | ------------------------ | ----- | * | rotator | Rotate | | * | boxRotateTopLeft | Rotate | Invisible | * | boxRotateTopRight | Rotate | Invisible | * | boxRotateBottomLeft | Rotate | Invisible | * | boxRotateBottomRight | Rotate | Invisible | * | topLeft | Scale | | * | topCenter | Scale | | * | topRight | Scale | | * | middleLeft | Scale | | * | middleCenter | Scale | This cannot be enabled! | * | middleRight | Scale | | * | bottomLeft | Scale | | * | bottomCenter | Scale | | * | bottomRight | Scale | | * | skewHorizontal | Skew | Applies vertical shear. Handle segment is horizontal at skew.y = 0! | * | skewVertical | Skew | Applied horizontal shear. Handle segment is vertical at skew.x = 0! | */ constructor(options?: Partial); /** The list of enabled handles, if applied manually. */ get enabledHandles(): Array; set enabledHandles(value: Array); /** The currently applied handle style. If you have edited the transformer handles directly, this may be inaccurate. */ get handleStyle(): Partial; set handleStyle(value: Partial); /** This will enable the rotate handles. */ get rotateEnabled(): boolean; set rotateEnabled(value: boolean); /** This will enable the scale handles. */ get scaleEnabled(): boolean; set scaleEnabled(value: boolean); /** This will enable the skew handles. */ get skewEnabled(): boolean; set skewEnabled(value: boolean); /** * This is the type of transformation being applied by the user on the group. It can be inaccurate if you call one of * `translateGroup`, `scaleGroup`, `rotateGroup`, `skewGroup` without calling `commitGroup` afterwards. * * @readonly */ get transformType(): 'translate' | 'scale' | 'rotate' | 'skew' | 'none'; /** The currently applied wireframe style. */ get wireframeStyle(): Partial; set wireframeStyle(value: Partial); /** * @param forceUpdate - forces a recalculation of the group bounds * @returns the oriented bounding box of the wireframe */ getGroupBounds(forceUpdate?: boolean): OrientedBounds; /** * This will translate the group by {@code delta} in their world-space. * * NOTE: There is no handle that provides translation. The user drags the transformer directly. * * @param delta */ translateGroup: (delta: Point) => void; /** * This will rotate the group such that the handle will come to {@code pointerPosition}. * * @param handle - the rotator handle was dragged * @param pointerPosition - the new pointer position, in screen space */ rotateGroup: (handle: RotateHandle, pointerPosition: Point) => void; /** * This will scale the group such that the scale handle will come under {@code pointerPosition}. * * @param handle - the scaling handle that was dragged * @param pointerPosition - the new pointer position, in screen space */ scaleGroup: (handle: ScaleHandle, pointerPosition: Point) => void; /** * This will skew the group such that the skew handle would move to the {@code pointerPosition}. * * @param handle * @param pointerPosition - pointer position, in screen space */ skewGroup: (handle: SkewHandle, pointerPosition: Point) => void; /** * This is called after the user finishes dragging a handle. If {@link this.transientGroupTilt} is enabled, it will * reset the rotation of this group (if more than one display-object is grouped). */ commitGroup: () => void; /** * This will update the transformer's geometry and render it to the canvas. * * @override * @param renderer */ render(renderer: Renderer): void; /** Recalculates the transformer's geometry. This is called on each render. */ protected draw(): void; /** * Draw the handles and any remaining parts of the wireframe. * * @param groupBounds */ protected drawHandles(groupBounds: OrientedBounds): void; /** Called on the `pointerdown` event. You must call the super implementation. */ protected onPointerDown(e: FederatedPointerEvent): void; /** Called on the `pointermove` event. You must call the super implementation. */ protected onPointerMove(e: FederatedPointerEvent): void; /** Called on the `pointerup` and `pointerupoutside` events. You must call the super implementation. */ protected onPointerUp(e: FederatedPointerEvent): void; /** * Applies the given transformation matrix {@code delta} to all the display-objects in the group. * * @param delta - transformation matrix * @param skipUpdate - whether to skip updating the group-bounds after applying the transform */ protected prependTransform(delta: Matrix, skipUpdate?: boolean): void; /** * Recalculates {@code this.groupBounds} at the same angle. * * @param rotation - override the group's rotation */ private updateGroupBounds; /** * Snaps the given {@code angle} to one of the snapping angles, if possible. * * @param angle - the input angle * @param snapTolerance - the maximum difference b/w the given angle & a snapping angle * @param snaps - the snapping angles * @returns the snapped angle */ private snapAngle; /** * Swap the handles represented by the two {@code TransformerHandle} instances. * * @param handle0 * @param handle1 */ private swapHandles; /** Set cursor from {@code this.cursors} based on the handle hovered currently. */ private setCursorFromHoveredHandle; /** * Projects {@code input} from the group's world space into the transformer's local space, and puts the result * into {@code output}. * * @param input * @param output * @returns the output */ projectToLocal(input: Point, output?: Point): Point; /** * Calculates the positions of the four corners of the display-object. The quadrilateral formed by * these points will be the tightest fit around it. * * @param displayObject - The display object whose corners are to be calculated * @param transform - The transform applied on the display-object. By default, this is its world-transform * @param corners - Optional array of four points to put the result into * @param index - Optional index into "corners" * @returns an array of four points holding the positions of the corners */ static calculateTransformedCorners(displayObject: DisplayObject, transform?: Matrix, corners?: Point[], index?: number): Point[]; /** * Calculates the oriented bounding box of the display-object. This would not bending with any skew * applied on the display-object, i.e. it is guaranteed to be rectangular. * * @param displayObject * @param bounds - the bounds instance to set */ static calculateOrientedBounds(displayObject: DisplayObject, bounds?: OrientedBounds): OrientedBounds; /** * Calculates the oriented bounding box of a group of display-objects at a specific angle. * * @param group * @param rotation * @param bounds * @param skipUpdate */ static calculateGroupOrientedBounds(group: DisplayObject[], rotation: number, bounds?: OrientedBounds, skipUpdate?: boolean): OrientedBounds; } export { Transformer_2 as Transformer } /** * The transfomer handle base implementation. * * @extends PIXI.Graphics */ export declare class TransformerHandle extends Graphics_ { protected readonly transformer: Transformer_2; onHandleDelta: (pointerPosition: Point) => void; onHandleCommit: () => void; protected _handle: Handle; protected _style: ITransformerHandleStyle; protected _dirty: boolean; private _pointerDown; private _pointerDragging; private _pointerPosition; private _pointerMoveTarget; /** * @param {Transformer} transformer * @param {string} handle - the type of handle being drawn * @param {object} styleOpts - styling options passed by the user * @param {function} handler - handler for drag events, it receives the pointer position; used by {@code onDrag}. * @param {function} commit - handler for drag-end events. * @param {string}[cursor='move'] - a custom cursor to be applied on this handle */ constructor(transformer: Transformer_2, handle: Handle, styleOpts: Partial, handler: (pointerPosition: Point) => void, commit: () => void, cursor?: string); get handle(): Handle; set handle(handle: Handle); /** * The currently applied handle style. */ get style(): Partial; set style(value: Partial); render(renderer: Renderer): void; /** * Redraws the handle's geometry. This is called on a `render` if {@code this._dirty} is true. */ protected draw(): void; /** * Handles the `pointerdown` event. You must call the super implementation. * * @param e */ protected onPointerDown(e: FederatedPointerEvent): void; /** * Handles the `pointermove` event. You must call the super implementation. * * @param e */ protected onPointerMove(e: FederatedPointerEvent): void; /** * Handles the `pointerup` and `pointerupoutside` events. You must call the super implementation. * * @param e */ protected onPointerUp(e: FederatedPointerEvent): void; /** * Called on the first `pointermove` when {@code this._pointerDown} is true. You must call the super implementation. * * @param e */ protected onDragStart(e: FederatedPointerEvent): void; /** * Called on a `pointermove` when {@code this._pointerDown} & {@code this._pointerDragging}. * * @param e */ protected onDrag(e: FederatedPointerEvent): void; /** * Called on a `pointerup` or `pointerupoutside` & {@code this._pointerDragging} was true. * * @param _ */ protected onDragEnd(_: FederatedPointerEvent): void; } /** * The transformer's wireframe is drawn using this class. * * @ignore * @public * @extends PIXI.Graphics */ export declare class TransformerWireframe extends Graphics__2 { protected transformer: Transformer_2; /** * The four scaling "edges" (or wide handles) for box-scaling. {@link TransformerWireframe#drawBoxScalingTolerance} * should draw into these. * * @type {PIXI.Graphics[]} */ protected boxScalingHandles: [GraphicsT_, GraphicsT_, GraphicsT_, GraphicsT_]; constructor(transformer: Transformer_2); /** * Detects which type of box-handle, if any, the pointer clicked on in the wireframe. * * @param groupBounds * @param projectionTransform * @param pointerPosition */ hitHandleType(groupBounds: OrientedBounds, projectionTransform: Matrix, pointerPosition: Point): Handle; /** * Draws the bounding box into the wireframe. * * @param bounds */ drawBounds(bounds: OrientedBounds | AxisAlignedBounds): void; /** * Draws around edges of the bounding box to capture pointer events within * {@link Transformer#boxScalingTolerance}. * * @param bounds * @param boxScalingTolerance */ drawBoxScalingTolerance(bounds: OrientedBounds, boxScalingTolerance?: number): void; /** * Draws square-shaped tolerance regions for capturing pointer events within {@link Transformer#boxRotationTolernace} * of the four corners of the group bounding box. The square are cut in the interior region of the group bounds. */ drawBoxRotationTolerance(): void; /** * Alias for {@link Transformer#projectToLocal}. The transform of the wireframe should equal that * of the transformer itself. * * @param input * @param output */ protected projectToLocal(input: Point, output: Point): Point; } export { }