import { Bezier } from 'bezier-js'; import { createSimpleSchema, list, object, serializable } from 'serializr'; import { ScriptingGlobals } from '../client/util/ScriptingGlobals'; import { Deserializable } from '../client/util/SerializationHelper'; import { Copy, ToScriptString, ToString } from './FieldSymbols'; import { ObjectField } from './ObjectField'; // Helps keep track of the current ink tool in use. export enum InkTool { None = 'none', Pen = 'pen', Highlighter = 'highlighter', Eraser = 'eraser', Stamp = 'stamp', Write = 'write', PresentationPin = 'presentationpin', } // Defines a point in an ink as a pair of x- and y-coordinates. export interface PointData { X: number; Y: number; } export type Segment = Array; // Defines an ink as an array of points. export type InkData = Array; export interface ControlPoint { X: number; Y: number; I: number; } export interface HandlePoint { X: number; Y: number; I: number; dot1: number; dot2: number; } export interface HandleLine { X1: number; Y1: number; X2: number; Y2: number; X3: number; Y3: number; dot1: number; dot2: number; } const pointSchema = createSimpleSchema({ X: true, Y: true, }); const strokeDataSchema = createSimpleSchema({ pathData: list(object(pointSchema)), '*': true, }); @Deserializable('ink') export class InkField extends ObjectField { @serializable(list(object(strokeDataSchema))) readonly inkData: InkData; constructor(data: InkData) { super(); this.inkData = data; } /** * Extacts a simple segment from a compound Bezier curve * @param segIndex the start index of the simple bezier segment to extact (eg., 0, 4, 8, ...) */ public static Segment(inkData: InkData, segIndex: number) { return new Bezier(inkData.slice(segIndex, segIndex + 4).map(pt => ({ x: pt.X, y: pt.Y }))); } [Copy]() { return new InkField(this.inkData); } [ToScriptString]() { return 'new InkField([' + this.inkData.map(i => `{X: ${i.X}, Y: ${i.Y}}`) + '])'; } [ToString]() { return 'InkField'; } } ScriptingGlobals.add('InkField', InkField);