@stuly/anode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/core/context.ts"],"sourcesContent":["import { Entity, Link, LinkKind, Socket, SocketKind, Vec2, Group } from './elements';\nimport { QuadTree, Rect } from './layout';\nimport { HistoryManager, type HistoryAction, type Command } from './history';\n\nexport type EntityCallback<T> = (entity: Entity<T>) => void;\nexport type LinkCallback = (link: Link) => void;\nexport type SocketCallback = (socket: Socket) => void;\nexport type EntityMoveCallback<T> = (entity: Entity<T>, pos: Vec2) => void;\nexport type GroupCallback = (group: Group) => void;\nexport type SocketValueCallback = (socket: Socket, value: any) => void;\nexport type CallbackHandle = number;\n\nexport class Context<T = any> {\n private eid: number = 0;\n private lid: number = 0;\n private sid: number = 0;\n private gid: number = 0;\n\n private freeEids: number[] = [];\n private freeLids: number[] = [];\n private freeSids: number[] = [];\n private freeGids: number[] = [];\n\n private callbackIds: number = 0;\n private freeCallbackIds: number[] = [];\n\n private entityCreateCallbacks: Map<number, EntityCallback<T>> = new Map();\n private entityDropCallbacks: Map<number, EntityCallback<T>> = new Map();\n private entityMoveCallbacks: Map<number, EntityMoveCallback<T>> = new Map();\n private socketMoveCallbacks: Map<number, SocketCallback> = new Map();\n private socketValueCallbacks: Map<number, SocketValueCallback> = new Map();\n\n private linkCreateCallbacks: Map<number, LinkCallback> = new Map();\n private linkDropCallbacks: Map<number, LinkCallback> = new Map();\n private linkUpdateCallbacks: Map<number, LinkCallback> = new Map();\n\n private socketCreateCallbacks: Map<number, SocketCallback> = new Map();\n private socketDropCallbacks: Map<number, SocketCallback> = new Map();\n\n private groupCreateCallbacks: Map<number, GroupCallback> = new Map();\n private groupDropCallbacks: Map<number, GroupCallback> = new Map();\n private bulkChangeCallbacks: Map<number, () => void> = new Map();\n\n entities: Map<number, Entity<T>> = new Map();\n links: Map<number, Link> = new Map();\n sockets: Map<number, Socket> = new Map();\n groups: Map<number, Group> = new Map();\n\n quadTree: QuadTree<number> = new QuadTree(new Rect(-100000, -100000, 200000, 200000));\n history: HistoryManager = new HistoryManager();\n private isApplyingHistory: boolean = false;\n private currentBatch: HistoryAction[] | null = null;\n private currentUndoBatch: HistoryAction[] | null = null;\n private isBatchingQuadTree: boolean = false;\n\n private getNextEid() {\n return this.freeEids.pop() ?? this.eid++;\n }\n private getNextLid() {\n return this.freeLids.pop() ?? this.lid++;\n }\n private getNextSid() {\n return this.freeSids.pop() ?? this.sid++;\n }\n private getNextGid() {\n return this.freeGids.pop() ?? this.gid++;\n }\n private getNextCallbackHandle(): CallbackHandle {\n return this.freeCallbackIds.pop() ?? this.callbackIds++;\n }\n\n private setupEntity(entity: Entity<T>) {\n entity.onMove((pos) => {\n this.updateQuadTree();\n for (const cb of this.entityMoveCallbacks.values()) {\n try {\n cb(entity, this.getWorldPosition(entity.id));\n } catch (err) {\n console.error(err);\n }\n }\n });\n }\n\n notifyBulkChange() {\n for (const cb of this.bulkChangeCallbacks.values()) {\n try {\n cb();\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n registerBulkChangeListener(cb: () => void): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.bulkChangeCallbacks.set(handle, cb);\n return handle;\n }\n\n setSocketValue(socketId: number, value: any) {\n const socket = this.sockets.get(socketId);\n if (!socket) return;\n\n socket.value = value;\n\n // Notify listeners for this specific socket\n for (const cb of this.socketValueCallbacks.values()) {\n cb(socket, value);\n }\n\n // If it's an OUTPUT, propagate to all linked INPUTs\n if (socket.kind === SocketKind.OUTPUT) {\n for (const link of this.links.values()) {\n if (link.from === socketId) {\n this.setSocketValue(link.to, value);\n }\n }\n }\n }\n\n registerSocketValueListener(cb: SocketValueCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.socketValueCallbacks.set(handle, cb);\n return handle;\n }\n\n record(\n doActions: HistoryAction | HistoryAction[],\n undoActions: HistoryAction | HistoryAction[],\n label?: string\n ) {\n if (this.isApplyingHistory) return;\n\n // If we are in a batch, we don't record individual actions to history\n // We let the batch() method handle the combined history entry\n if (this.currentBatch) {\n return;\n }\n\n const das = Array.isArray(doActions) ? doActions : [doActions];\n const uas = Array.isArray(undoActions) ? undoActions : [undoActions];\n\n this.history.push({\n do: das,\n undo: uas,\n label: label ?? 'Action',\n timestamp: Date.now()\n });\n }\n\n batch(fn: () => void, label?: string) {\n if (this.currentBatch) {\n fn();\n return;\n }\n\n const oldApplying = this.isApplyingHistory;\n const oldBatchingQT = this.isBatchingQuadTree;\n const beforeState = this.toJSON();\n\n try {\n this.isApplyingHistory = true;\n this.isBatchingQuadTree = true;\n fn();\n\n this.isBatchingQuadTree = oldBatchingQT;\n this.updateQuadTree();\n\n const afterState = this.toJSON();\n\n this.history.push({\n do: [{ type: 'FROM_JSON', data: afterState }],\n undo: [{ type: 'FROM_JSON', data: beforeState }],\n label: label ?? 'Batch Action',\n timestamp: Date.now()\n });\n } finally {\n this.isApplyingHistory = oldApplying;\n this.isBatchingQuadTree = oldBatchingQT;\n }\n }\n undo() {\n const cmd = this.history.undoStack.pop();\n if (!cmd) return;\n this.isApplyingHistory = true;\n this.isBatchingQuadTree = true;\n try {\n for (let i = cmd.undo.length - 1; i >= 0; i--) {\n this.applyAction(cmd.undo[i]!);\n }\n this.isBatchingQuadTree = false;\n this.updateQuadTree();\n this.notifyBulkChange();\n this.history.redoStack.push(cmd);\n } finally {\n this.isApplyingHistory = false;\n this.isBatchingQuadTree = false;\n }\n }\n\n redo() {\n const cmd = this.history.redoStack.pop();\n if (!cmd) return;\n this.isApplyingHistory = true;\n this.isBatchingQuadTree = true;\n try {\n for (const action of cmd.do) {\n this.applyAction(action);\n }\n this.isBatchingQuadTree = false;\n this.updateQuadTree();\n this.notifyBulkChange();\n this.history.undoStack.push(cmd);\n } finally {\n this.isApplyingHistory = false;\n this.isBatchingQuadTree = false;\n }\n }\n\n private applyAction(action: HistoryAction) {\n switch (action.type) {\n case 'FROM_JSON': {\n this.fromJSON(action.data);\n break;\n }\n case 'MOVE_ENTITY': {\n const entity = this.entities.get(action.id);\n if (entity) {\n entity.position.set(action.to.x, action.to.y);\n for (const cb of this.entityMoveCallbacks.values())\n cb(entity, this.getWorldPosition(entity.id));\n this.updateQuadTree();\n }\n break;\n }\n case 'MOVE_GROUP': {\n const group = this.groups.get(action.id);\n if (group) {\n const dx = action.to.x - action.from.x;\n const dy = action.to.y - action.from.y;\n const oldApplying = this.isApplyingHistory;\n this.isApplyingHistory = true;\n try {\n this.moveGroup(group, dx, dy);\n } finally {\n this.isApplyingHistory = oldApplying;\n }\n }\n break;\n }\n case 'CREATE_ENTITY': {\n const entity = new Entity(action.id, action.inner);\n entity.position.set(action.position.x, action.position.y);\n this.entities.set(entity.id, entity);\n this.eid = Math.max(this.eid, entity.id + 1);\n\n this.setupEntity(entity);\n\n if (action.parentId !== null) {\n this.addToGroup(action.parentId, entity.id);\n }\n for (const cb of this.entityCreateCallbacks.values()) cb(entity);\n this.updateQuadTree();\n break;\n }\n case 'DROP_ENTITY': {\n const entity = this.entities.get(action.id);\n if (entity) {\n const oldApplying = this.isApplyingHistory;\n this.isApplyingHistory = true;\n try {\n this.dropEntity(entity);\n } finally {\n this.isApplyingHistory = oldApplying;\n }\n }\n break;\n }\n case 'CREATE_LINK': {\n const from = this.sockets.get(action.from);\n const to = this.sockets.get(action.to);\n if (from && to) {\n const link = new Link(action.id, from.id, to.id, action.kind, action.inner);\n this.links.set(link.id, link);\n this.lid = Math.max(this.lid, link.id + 1);\n for (const cb of this.linkCreateCallbacks.values()) cb(link);\n }\n break;\n }\n case 'DROP_LINK': {\n const link = this.links.get(action.id);\n if (link) {\n const oldApplying = this.isApplyingHistory;\n this.isApplyingHistory = true;\n try {\n this.dropLink(link);\n } finally {\n this.isApplyingHistory = oldApplying;\n }\n }\n break;\n }\n case 'UPDATE_LINK': {\n const link = this.links.get(action.id);\n if (link) {\n link.from = action.from.new;\n link.to = action.to.new;\n if (action.waypoints) {\n link.waypoints = action.waypoints.new.map((p) => new Vec2(p.x, p.y));\n }\n for (const cb of this.linkUpdateCallbacks.values()) cb(link);\n }\n break;\n }\n case 'ADD_TO_GROUP': {\n this.addToGroup(action.groupId, action.entityId);\n break;\n }\n case 'REMOVE_FROM_GROUP': {\n this.removeFromGroup(action.groupId, action.entityId);\n break;\n }\n case 'CREATE_SOCKET': {\n const entity = this.entities.get(action.entityId);\n if (entity) {\n const socket = new Socket(action.id, entity.id, action.kind, action.name);\n socket.offset.set(action.offset.x, action.offset.y);\n this.sockets.set(socket.id, socket);\n entity.sockets.set(socket.id, socket);\n this.sid = Math.max(this.sid, socket.id + 1);\n for (const cb of this.socketCreateCallbacks.values()) cb(socket);\n }\n break;\n }\n case 'DROP_SOCKET': {\n const socket = this.sockets.get(action.id);\n if (socket) {\n const oldApplying = this.isApplyingHistory;\n this.isApplyingHistory = true;\n try {\n this.dropSocket(socket);\n } finally {\n this.isApplyingHistory = oldApplying;\n }\n }\n break;\n }\n }\n }\n\n registerEntityCreateListener(cb: EntityCallback<T>): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.entityCreateCallbacks.set(handle, cb);\n return handle;\n }\n\n registerEntityDropListener(cb: EntityCallback<T>): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.entityDropCallbacks.set(handle, cb);\n return handle;\n }\n\n registerEntityMoveListener(cb: EntityMoveCallback<T>): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.entityMoveCallbacks.set(handle, cb);\n return handle;\n }\n\n registerSocketMoveListener(cb: SocketCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.socketMoveCallbacks.set(handle, cb);\n return handle;\n }\n\n notifySocketMove(socket: Socket) {\n for (const cb of this.socketMoveCallbacks.values()) {\n try {\n cb(socket);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n registerLinkCreateListener(cb: LinkCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.linkCreateCallbacks.set(handle, cb);\n return handle;\n }\n\n registerLinkDropListener(cb: LinkCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.linkDropCallbacks.set(handle, cb);\n return handle;\n }\n\n registerLinkUpdateListener(cb: LinkCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.linkUpdateCallbacks.set(handle, cb);\n return handle;\n }\n\n registerSocketCreateListener(cb: SocketCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.socketCreateCallbacks.set(handle, cb);\n return handle;\n }\n\n registerSocketDropListener(cb: SocketCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.socketDropCallbacks.set(handle, cb);\n return handle;\n }\n\n registerGroupCreateListener(cb: GroupCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.groupCreateCallbacks.set(handle, cb);\n return handle;\n }\n\n registerGroupDropListener(cb: GroupCallback): CallbackHandle {\n const handle = this.getNextCallbackHandle();\n this.groupDropCallbacks.set(handle, cb);\n return handle;\n }\n\n unregisterListener(handle: CallbackHandle) {\n const deleted =\n this.linkCreateCallbacks.delete(handle) ||\n this.linkDropCallbacks.delete(handle) ||\n this.linkUpdateCallbacks.delete(handle) ||\n this.entityCreateCallbacks.delete(handle) ||\n this.entityDropCallbacks.delete(handle) ||\n this.entityMoveCallbacks.delete(handle) ||\n this.socketCreateCallbacks.delete(handle) ||\n this.socketDropCallbacks.delete(handle) ||\n this.socketMoveCallbacks.delete(handle) ||\n this.groupCreateCallbacks.delete(handle) ||\n this.groupDropCallbacks.delete(handle) ||\n this.bulkChangeCallbacks.delete(handle);\n\n if (deleted) {\n this.freeCallbackIds.push(handle);\n return true;\n }\n return false;\n }\n\n newGroup(name: string = '') {\n const group = new Group(this.getNextGid(), name);\n this.groups.set(group.id, group);\n for (const cb of this.groupCreateCallbacks.values()) {\n try {\n cb(group);\n } catch (err) {\n console.error(err);\n }\n }\n return group;\n }\n\n dropGroup(group: Group) {\n if (this.groups.delete(group.id)) {\n if (group.parentId !== null) {\n this.removeGroupFromGroup(group.parentId, group.id);\n }\n // Detach all entities\n for (const eid of group.entities) {\n const entity = this.entities.get(eid);\n if (entity) entity.parentId = null;\n }\n // Detach all nested groups\n for (const gid of group.groups) {\n const childGroup = this.groups.get(gid);\n if (childGroup) childGroup.parentId = null;\n }\n\n this.freeGids.push(group.id);\n for (const cb of this.groupDropCallbacks.values()) {\n try {\n cb(group);\n } catch (err) {\n console.error(err);\n }\n }\n this.updateQuadTree();\n }\n }\n\n getWorldPosition(entityId: number): Vec2 {\n const entity = this.entities.get(entityId);\n if (!entity) return new Vec2();\n\n const pos = entity.position.clone();\n let currentParentId = entity.parentId;\n\n while (currentParentId !== null) {\n const parent = this.groups.get(currentParentId);\n if (!parent) break;\n pos.x += parent.position.x;\n pos.y += parent.position.y;\n currentParentId = parent.parentId;\n }\n\n return pos;\n }\n\n getGroupWorldPosition(groupId: number): Vec2 {\n const group = this.groups.get(groupId);\n if (!group) return new Vec2();\n\n const pos = group.position.clone();\n let currentParentId = group.parentId;\n\n while (currentParentId !== null) {\n const parent = this.groups.get(currentParentId);\n if (!parent) break;\n pos.x += parent.position.x;\n pos.y += parent.position.y;\n currentParentId = parent.parentId;\n }\n\n return pos;\n }\n\n moveGroup(group: Group, dx: number, dy: number) {\n const oldBatching = this.isBatchingQuadTree;\n this.isBatchingQuadTree = true;\n\n group.position.x += dx;\n group.position.y += dy;\n\n // Notify about moves for all nested entities recursively\n const notifyRecursive = (g: Group) => {\n for (const eid of g.entities) {\n const entity = this.entities.get(eid);\n if (entity) {\n for (const cb of this.entityMoveCallbacks.values()) {\n cb(entity, this.getWorldPosition(eid));\n }\n }\n }\n for (const gid of g.groups) {\n const childGroup = this.groups.get(gid);\n if (childGroup) notifyRecursive(childGroup);\n }\n };\n\n try {\n notifyRecursive(group);\n } finally {\n this.isBatchingQuadTree = oldBatching;\n this.updateQuadTree();\n }\n }\n\n addToGroup(groupId: number, entityId: number) {\n const group = this.groups.get(groupId);\n const entity = this.entities.get(entityId);\n if (group && entity) {\n // If already in a group, remove it\n if (entity.parentId !== null) {\n this.removeFromGroup(entity.parentId, entityId);\n }\n group.add(entityId);\n entity.parentId = groupId;\n this.updateQuadTree();\n }\n }\n\n removeFromGroup(groupId: number, entityId: number) {\n const group = this.groups.get(groupId);\n const entity = this.entities.get(entityId);\n if (group && entity) {\n group.remove(entityId);\n entity.parentId = null;\n this.updateQuadTree();\n }\n }\n\n addGroupToGroup(parentGroupId: number, childGroupId: number) {\n const parent = this.groups.get(parentGroupId);\n const child = this.groups.get(childGroupId);\n if (parent && child && parentGroupId !== childGroupId) {\n if (child.parentId !== null) {\n this.removeGroupFromGroup(child.parentId, childGroupId);\n }\n parent.addGroup(childGroupId);\n child.parentId = parentGroupId;\n this.updateQuadTree();\n }\n }\n\n removeGroupFromGroup(parentGroupId: number, childGroupId: number) {\n const parent = this.groups.get(parentGroupId);\n const child = this.groups.get(childGroupId);\n if (parent && child) {\n parent.removeGroup(childGroupId);\n child.parentId = null;\n this.updateQuadTree();\n }\n }\n\n updateQuadTree() {\n if (this.isBatchingQuadTree) return;\n\n this.quadTree.clear();\n for (const entity of this.entities.values()) {\n const entityWorldPos = this.getWorldPosition(entity.id);\n // Index entity top-left\n this.quadTree.insert(entityWorldPos, entity.id);\n\n // Index every socket world position\n for (const socket of entity.sockets.values()) {\n this.quadTree.insert(\n new Vec2(entityWorldPos.x + socket.offset.x, entityWorldPos.y + socket.offset.y),\n entity.id\n );\n }\n }\n }\n\n newEntity(inner: T, forcedId?: number) {\n const id = forcedId ?? this.getNextEid();\n const ett = new Entity(id, inner);\n this.entities.set(ett.id, ett);\n if (forcedId !== undefined) {\n this.eid = Math.max(this.eid, forcedId + 1);\n }\n\n this.setupEntity(ett);\n\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'CREATE_ENTITY',\n id: ett.id,\n inner: ett.inner,\n position: { ...ett.position },\n parentId: ett.parentId\n },\n {\n type: 'DROP_ENTITY',\n id: ett.id,\n inner: ett.inner,\n position: { ...ett.position },\n parentId: ett.parentId\n },\n 'Create Entity'\n );\n }\n\n for (const cb of this.entityCreateCallbacks.values()) {\n try {\n cb(ett);\n } catch (err) {\n console.error(err);\n }\n }\n this.updateQuadTree();\n return ett;\n }\n\n dropEntity(entity: Entity<T>) {\n if (this.entities.has(entity.id)) {\n this.batch(() => {\n // Record entity drop itself\n this.record(\n {\n type: 'DROP_ENTITY',\n id: entity.id,\n inner: entity.inner,\n position: { ...entity.position },\n parentId: entity.parentId\n },\n {\n type: 'CREATE_ENTITY',\n id: entity.id,\n inner: entity.inner,\n position: { ...entity.position },\n parentId: entity.parentId\n },\n 'Drop Entity'\n );\n\n if (entity.parentId !== null) {\n this.removeFromGroup(entity.parentId, entity.id);\n }\n\n this.entities.delete(entity.id);\n\n // Drop all sockets of this entity\n for (const socket of entity.sockets.values()) {\n this.dropSocket(socket);\n }\n\n this.freeEids.push(entity.id);\n for (const cb of this.entityDropCallbacks.values()) {\n try {\n cb(entity);\n } catch (err) {\n console.error(err);\n }\n }\n this.updateQuadTree();\n }, 'Drop Entity');\n }\n }\n\n newSocket(entity: Entity<T>, kind: SocketKind, name: string = '', forcedId?: number) {\n const id = forcedId ?? this.getNextSid();\n const socket = new Socket(id, entity.id, kind, name);\n this.sockets.set(socket.id, socket);\n entity.sockets.set(socket.id, socket);\n if (forcedId !== undefined) {\n this.sid = Math.max(this.sid, forcedId + 1);\n }\n\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'CREATE_SOCKET',\n id: socket.id,\n entityId: entity.id,\n kind,\n name,\n offset: { ...socket.offset }\n },\n {\n type: 'DROP_SOCKET',\n id: socket.id,\n entityId: entity.id,\n kind,\n name,\n offset: { ...socket.offset }\n },\n 'Create Socket'\n );\n }\n\n for (const cb of this.socketCreateCallbacks.values()) {\n try {\n cb(socket);\n } catch (err) {\n console.error(err);\n }\n }\n return socket;\n }\n\n dropSocket(socket: Socket) {\n if (this.sockets.delete(socket.id)) {\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'DROP_SOCKET',\n id: socket.id,\n entityId: socket.entityId,\n kind: socket.kind,\n name: socket.name,\n offset: { ...socket.offset }\n },\n {\n type: 'CREATE_SOCKET',\n id: socket.id,\n entityId: socket.entityId,\n kind: socket.kind,\n name: socket.name,\n offset: { ...socket.offset }\n },\n 'Drop Socket'\n );\n }\n const entity = this.entities.get(socket.entityId);\n if (entity) {\n entity.sockets.delete(socket.id);\n }\n\n // Drop all links connected to this socket\n for (const link of this.links.values()) {\n if (link.from === socket.id || link.to === socket.id) {\n this.dropLink(link);\n }\n }\n\n this.freeSids.push(socket.id);\n for (const cb of this.socketDropCallbacks.values()) {\n try {\n cb(socket);\n } catch (err) {\n console.error(err);\n }\n }\n }\n }\n\n newLink(\n from: Socket,\n to: Socket,\n kind: LinkKind = LinkKind.BEZIER,\n forcedId?: number,\n inner: any = {}\n ) {\n if (!this.canLink(from, to)) {\n return null;\n }\n const id = forcedId ?? this.getNextLid();\n const link = new Link(id, from.id, to.id, kind, inner);\n this.links.set(link.id, link);\n if (forcedId !== undefined) {\n this.lid = Math.max(this.lid, forcedId + 1);\n }\n\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'CREATE_LINK',\n id: link.id,\n from: link.from,\n to: link.to,\n kind: link.kind,\n inner: link.inner\n },\n {\n type: 'DROP_LINK',\n id: link.id,\n from: link.from,\n to: link.to,\n kind: link.kind,\n inner: link.inner\n },\n 'Create Link'\n );\n }\n\n // Immediate propagation: If the source has a value, push it to the target\n if (from.value !== null) {\n this.setSocketValue(to.id, from.value);\n }\n\n for (const cb of this.linkCreateCallbacks.values()) {\n try {\n cb(link);\n } catch (err) {\n console.error(err);\n }\n }\n return link;\n }\n\n updateLink(link: Link, fromId?: number, toId?: number) {\n const oldFrom = link.from;\n const oldTo = link.to;\n const newFrom = fromId ?? oldFrom;\n const newTo = toId ?? oldTo;\n\n if (oldFrom === newFrom && oldTo === newTo) return;\n\n const fromSocket = this.sockets.get(newFrom);\n const toSocket = this.sockets.get(newTo);\n\n if (!fromSocket || !toSocket || !this.canLink(fromSocket, toSocket)) {\n return;\n }\n\n const oldWaypoints = link.waypoints.map((p) => ({ x: p.x, y: p.y }));\n\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'UPDATE_LINK',\n id: link.id,\n from: { old: oldFrom, new: newFrom },\n to: { old: oldTo, new: newTo },\n waypoints: { old: oldWaypoints, new: oldWaypoints }\n },\n {\n type: 'UPDATE_LINK',\n id: link.id,\n from: { old: newFrom, new: oldFrom },\n to: { old: newTo, new: oldTo },\n waypoints: { old: oldWaypoints, new: oldWaypoints }\n },\n 'Update Link'\n );\n }\n\n link.from = newFrom;\n link.to = newTo;\n\n for (const cb of this.linkUpdateCallbacks.values()) {\n try {\n cb(link);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n setLinkWaypoints(link: Link, waypoints: Vec2[]) {\n const oldWaypoints = link.waypoints.map((p) => ({ x: p.x, y: p.y }));\n const newWaypoints = waypoints.map((p) => ({ x: p.x, y: p.y }));\n\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'UPDATE_LINK',\n id: link.id,\n from: { old: link.from, new: link.from },\n to: { old: link.to, new: link.to },\n waypoints: { old: oldWaypoints, new: newWaypoints }\n },\n {\n type: 'UPDATE_LINK',\n id: link.id,\n from: { old: link.from, new: link.from },\n to: { old: link.to, new: link.to },\n waypoints: { old: newWaypoints, new: oldWaypoints }\n },\n 'Update Link Routing'\n );\n }\n\n link.waypoints = waypoints.map((p) => p.clone());\n\n for (const cb of this.linkUpdateCallbacks.values()) {\n try {\n cb(link);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n canLink(from: Socket, to: Socket) {\n if (from.id === to.id) return false;\n if (from.entityId === to.entityId) return false;\n if (from.kind === to.kind) return false;\n // Don't allow multiple links between same sockets\n for (const link of this.links.values()) {\n if (\n (link.from === from.id && link.to === to.id) ||\n (link.from === to.id && link.to === from.id)\n ) {\n return false;\n }\n }\n\n if (this.detectCycle(from, to)) {\n return false;\n }\n\n return true;\n }\n\n detectCycle(from: Socket, to: Socket): boolean {\n const visited = new Set<number>();\n const stack = [to.entityId];\n\n while (stack.length > 0) {\n const currentEntityId = stack.pop()!;\n if (currentEntityId === from.entityId) return true;\n if (visited.has(currentEntityId)) continue;\n visited.add(currentEntityId);\n\n // Find all outgoing links from this entity\n const entity = this.entities.get(currentEntityId);\n if (!entity) continue;\n\n for (const socket of entity.sockets.values()) {\n if (socket.kind === SocketKind.OUTPUT) {\n for (const link of this.links.values()) {\n if (link.from === socket.id) {\n const targetSocket = this.sockets.get(link.to);\n if (targetSocket) {\n stack.push(targetSocket.entityId);\n }\n }\n }\n }\n }\n }\n\n return false;\n }\n\n dropLink(link: Link) {\n if (this.links.delete(link.id)) {\n if (!this.isApplyingHistory) {\n this.record(\n {\n type: 'DROP_LINK',\n id: link.id,\n from: link.from,\n to: link.to,\n kind: link.kind,\n inner: link.inner\n },\n {\n type: 'CREATE_LINK',\n id: link.id,\n from: link.from,\n to: link.to,\n kind: link.kind,\n inner: link.inner\n },\n 'Drop Link'\n );\n }\n this.freeLids.push(link.id);\n for (const cb of this.linkDropCallbacks.values()) {\n try {\n cb(link);\n } catch (err) {\n console.error(err);\n }\n }\n }\n }\n\n toJSON() {\n return {\n entities: Array.from(this.entities.values()).map((e) => ({\n id: e.id,\n position: { x: e.position.x, y: e.position.y },\n inner: e.inner,\n parentId: e.parentId,\n sockets: Array.from(e.sockets.values()).map((s) => ({\n id: s.id,\n kind: s.kind,\n name: s.name,\n offset: { x: s.offset.x, y: s.offset.y }\n }))\n })),\n links: Array.from(this.links.values()).map((l) => ({\n id: l.id,\n from: l.from,\n to: l.to,\n kind: l.kind,\n waypoints: l.waypoints.map((p) => ({ x: p.x, y: p.y })),\n inner: l.inner\n })),\n groups: Array.from(this.groups.values()).map((g) => ({\n id: g.id,\n name: g.name,\n entities: Array.from(g.entities),\n groups: Array.from(g.groups),\n position: { x: g.position.x, y: g.position.y },\n parentId: g.parentId\n }))\n };\n }\n\n fromJSON(data: any) {\n this.entities.clear();\n this.links.clear();\n this.sockets.clear();\n this.groups.clear();\n this.eid = 0;\n this.lid = 0;\n this.sid = 0;\n this.gid = 0;\n this.freeEids = [];\n this.freeLids = [];\n this.freeSids = [];\n this.freeGids = [];\n\n for (const eData of data.entities) {\n const entity = new Entity(eData.id, eData.inner);\n entity.position.set(eData.position.x, eData.position.y);\n entity.parentId = eData.parentId;\n this.entities.set(entity.id, entity);\n this.eid = Math.max(this.eid, entity.id + 1);\n\n this.setupEntity(entity);\n\n for (const sData of eData.sockets) {\n const socket = new Socket(sData.id, entity.id, sData.kind, sData.name);\n socket.offset.set(sData.offset.x, sData.offset.y);\n this.sockets.set(socket.id, socket);\n entity.sockets.set(socket.id, socket);\n this.sid = Math.max(this.sid, socket.id + 1);\n }\n }\n\n for (const lData of data.links) {\n const link = new Link(lData.id, lData.from, lData.to, lData.kind, lData.inner);\n if (lData.waypoints) {\n link.waypoints = lData.waypoints.map((p: any) => new Vec2(p.x, p.y));\n }\n this.links.set(link.id, link);\n this.lid = Math.max(this.lid, link.id + 1);\n }\n\n if (data.groups) {\n for (const gData of data.groups) {\n const group = new Group(gData.id, gData.name);\n group.position.set(gData.position.x, gData.position.y);\n group.parentId = gData.parentId;\n for (const eid of gData.entities) {\n group.add(eid);\n }\n if (gData.groups) {\n for (const gid of gData.groups) {\n group.addGroup(gid);\n }\n }\n this.groups.set(group.id, group);\n this.gid = Math.max(this.gid, group.id + 1);\n }\n }\n this.updateQuadTree();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ //#region src/core/elements.d.ts
2
+ declare class Vec2 {
3
+ x: number;
4
+ y: number;
5
+ constructor(x?: number, y?: number);
6
+ set(x: number, y: number): this;
7
+ copy(other: Vec2): this;
8
+ clone(): Vec2;
9
+ }
10
+ declare enum SocketKind {
11
+ INPUT = "INPUT",
12
+ OUTPUT = "OUTPUT"
13
+ }
14
+ /** A connection point on an entity */
15
+ declare class Socket {
16
+ #private;
17
+ entityId: number;
18
+ kind: SocketKind;
19
+ name: string;
20
+ offset: Vec2;
21
+ value: any;
22
+ constructor(id: number, entityId: number, kind: SocketKind, name?: string);
23
+ get id(): number;
24
+ }
25
+ /** An element of the node */
26
+ declare class Entity<T = any> {
27
+ #private;
28
+ inner: T;
29
+ position: Vec2;
30
+ sockets: Map<number, Socket>;
31
+ parentId: number | null;
32
+ constructor(id: number, inner: T);
33
+ setInner(newInner: T): void;
34
+ get id(): number;
35
+ move(x: number, y: number): void;
36
+ onMove(cb: (pos: Vec2) => void): () => void;
37
+ }
38
+ /** A group of entities */
39
+ declare class Group {
40
+ #private;
41
+ name: string;
42
+ entities: Set<number>;
43
+ groups: Set<number>;
44
+ position: Vec2;
45
+ parentId: number | null;
46
+ constructor(id: number, name?: string);
47
+ get id(): number;
48
+ add(entityId: number): void;
49
+ remove(entityId: number): void;
50
+ addGroup(groupId: number): void;
51
+ removeGroup(groupId: number): void;
52
+ }
53
+ declare enum LinkKind {
54
+ LINE = "LINE",
55
+ STEP = "STEP",
56
+ SMOOTH_STEP = "SMOOTH_STEP",
57
+ BEZIER = "BEZIER"
58
+ }
59
+ /** A connection between sockets */
60
+ declare class Link<T = any> {
61
+ #private;
62
+ from: number;
63
+ to: number;
64
+ kind: LinkKind;
65
+ waypoints: Vec2[];
66
+ inner: T;
67
+ constructor(id: number, from: number, to: number, kind?: LinkKind, inner?: T);
68
+ get id(): number;
69
+ }
70
+ //#endregion
71
+ export { Entity, Group, Link, LinkKind, Socket, SocketKind, Vec2 };
72
+ //# sourceMappingURL=elements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elements.d.ts","names":[],"sources":["../../src/core/elements.ts"],"mappings":";cAAa,IAAA;EAEF,CAAA;EACA,CAAA;cADA,CAAA,WACA,CAAA;EAGT,GAAA,CAAI,CAAA,UAAW,CAAA;EAMf,IAAA,CAAK,KAAA,EAAO,IAAA;EAMZ,KAAA,CAAA,GAAK,IAAA;AAAA;AAAA,aAKK,UAAA;EACV,KAAA;EACA,MAAA;AAAA;;cAIW,MAAA;EAAA;EAEX,QAAA;EACA,IAAA,EAAM,UAAA;EACN,IAAA;EACA,MAAA,EAAQ,IAAA;EACR,KAAA;cAEY,EAAA,UAAY,QAAA,UAAkB,IAAA,EAAM,UAAA,EAAY,IAAA;EAAA,IAOxD,EAAA,CAAA;AAAA;;cAMO,MAAA;EAAA;EACX,KAAA,EAAO,CAAA;EACP,QAAA,EAAU,IAAA;EACV,OAAA,EAAS,GAAA,SAAY,MAAA;EAGrB,QAAA;cAEY,EAAA,UAAY,KAAA,EAAO,CAAA;EAK/B,QAAA,CAAS,QAAA,EAAU,CAAA;EAAA,IAIf,EAAA,CAAA;EAIJ,IAAA,CAAK,CAAA,UAAW,CAAA;EAOhB,MAAA,CAAO,EAAA,GAAK,GAAA,EAAK,IAAA;AAAA;;cASN,KAAA;EAAA;EAEX,IAAA;EACA,QAAA,EAAU,GAAA;EACV,MAAA,EAAQ,GAAA;EACR,QAAA,EAAU,IAAA;EACV,QAAA;cAEY,EAAA,UAAY,IAAA;EAAA,IAKpB,EAAA,CAAA;EAIJ,GAAA,CAAI,QAAA;EAIJ,MAAA,CAAO,QAAA;EAIP,QAAA,CAAS,OAAA;EAIT,WAAA,CAAY,OAAA;AAAA;AAAA,aAKF,QAAA;EACV,IAAA;EACA,IAAA;EACA,WAAA;EACA,MAAA;AAAA;;cAIW,IAAA;EAAA;EAEX,IAAA;EACA,EAAA;EACA,IAAA,EAAM,QAAA;EACN,SAAA,EAAW,IAAA;EACX,KAAA,EAAO,CAAA;cAEK,EAAA,UAAY,IAAA,UAAc,EAAA,UAAY,IAAA,GAAI,QAAA,EAAkB,KAAA,GAAO,CAAA;EAAA,IAQ3E,EAAA,CAAA;AAAA"}
@@ -0,0 +1,130 @@
1
+ //#region src/core/elements.ts
2
+ var Vec2 = class Vec2 {
3
+ constructor(x = 0, y = 0) {
4
+ this.x = x;
5
+ this.y = y;
6
+ }
7
+ set(x, y) {
8
+ this.x = x;
9
+ this.y = y;
10
+ return this;
11
+ }
12
+ copy(other) {
13
+ this.x = other.x;
14
+ this.y = other.y;
15
+ return this;
16
+ }
17
+ clone() {
18
+ return new Vec2(this.x, this.y);
19
+ }
20
+ };
21
+ let SocketKind = /* @__PURE__ */ function(SocketKind) {
22
+ SocketKind["INPUT"] = "INPUT";
23
+ SocketKind["OUTPUT"] = "OUTPUT";
24
+ return SocketKind;
25
+ }({});
26
+ /** A connection point on an entity */
27
+ var Socket = class {
28
+ #id;
29
+ entityId;
30
+ kind;
31
+ name;
32
+ offset = new Vec2();
33
+ value = null;
34
+ constructor(id, entityId, kind, name = "") {
35
+ this.#id = id;
36
+ this.entityId = entityId;
37
+ this.kind = kind;
38
+ this.name = name;
39
+ }
40
+ get id() {
41
+ return this.#id;
42
+ }
43
+ };
44
+ /** An element of the node */
45
+ var Entity = class {
46
+ inner;
47
+ position = new Vec2();
48
+ sockets = /* @__PURE__ */ new Map();
49
+ #id;
50
+ #onMove = [];
51
+ parentId = null;
52
+ constructor(id, inner) {
53
+ this.#id = id;
54
+ this.inner = inner;
55
+ }
56
+ setInner(newInner) {
57
+ this.inner = newInner;
58
+ }
59
+ get id() {
60
+ return this.#id;
61
+ }
62
+ move(x, y) {
63
+ this.position.set(x, y);
64
+ for (const cb of this.#onMove) cb(this.position);
65
+ }
66
+ onMove(cb) {
67
+ this.#onMove.push(cb);
68
+ return () => {
69
+ this.#onMove = this.#onMove.filter((c) => c !== cb);
70
+ };
71
+ }
72
+ };
73
+ /** A group of entities */
74
+ var Group = class {
75
+ #id;
76
+ name;
77
+ entities = /* @__PURE__ */ new Set();
78
+ groups = /* @__PURE__ */ new Set();
79
+ position = new Vec2();
80
+ parentId = null;
81
+ constructor(id, name = "") {
82
+ this.#id = id;
83
+ this.name = name;
84
+ }
85
+ get id() {
86
+ return this.#id;
87
+ }
88
+ add(entityId) {
89
+ this.entities.add(entityId);
90
+ }
91
+ remove(entityId) {
92
+ this.entities.delete(entityId);
93
+ }
94
+ addGroup(groupId) {
95
+ this.groups.add(groupId);
96
+ }
97
+ removeGroup(groupId) {
98
+ this.groups.delete(groupId);
99
+ }
100
+ };
101
+ let LinkKind = /* @__PURE__ */ function(LinkKind) {
102
+ LinkKind["LINE"] = "LINE";
103
+ LinkKind["STEP"] = "STEP";
104
+ LinkKind["SMOOTH_STEP"] = "SMOOTH_STEP";
105
+ LinkKind["BEZIER"] = "BEZIER";
106
+ return LinkKind;
107
+ }({});
108
+ /** A connection between sockets */
109
+ var Link = class {
110
+ #id;
111
+ from;
112
+ to;
113
+ kind;
114
+ waypoints = [];
115
+ inner;
116
+ constructor(id, from, to, kind = LinkKind.LINE, inner = {}) {
117
+ this.#id = id;
118
+ this.from = from;
119
+ this.to = to;
120
+ this.kind = kind;
121
+ this.inner = inner;
122
+ }
123
+ get id() {
124
+ return this.#id;
125
+ }
126
+ };
127
+
128
+ //#endregion
129
+ export { Entity, Group, Link, LinkKind, Socket, SocketKind, Vec2 };
130
+ //# sourceMappingURL=elements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elements.js","names":["#id","#onMove"],"sources":["../../src/core/elements.ts"],"sourcesContent":["export class Vec2 {\n constructor(\n public x: number = 0,\n public y: number = 0\n ) {}\n\n set(x: number, y: number) {\n this.x = x;\n this.y = y;\n return this;\n }\n\n copy(other: Vec2) {\n this.x = other.x;\n this.y = other.y;\n return this;\n }\n\n clone() {\n return new Vec2(this.x, this.y);\n }\n}\n\nexport enum SocketKind {\n INPUT = 'INPUT',\n OUTPUT = 'OUTPUT'\n}\n\n/** A connection point on an entity */\nexport class Socket {\n #id: number;\n entityId: number;\n kind: SocketKind;\n name: string;\n offset: Vec2 = new Vec2();\n value: any = null;\n\n constructor(id: number, entityId: number, kind: SocketKind, name: string = '') {\n this.#id = id;\n this.entityId = entityId;\n this.kind = kind;\n this.name = name;\n }\n\n get id() {\n return this.#id;\n }\n}\n\n/** An element of the node */\nexport class Entity<T = any> {\n inner: T;\n position: Vec2 = new Vec2();\n sockets: Map<number, Socket> = new Map();\n #id: number;\n #onMove: ((pos: Vec2) => void)[] = [];\n parentId: number | null = null;\n\n constructor(id: number, inner: T) {\n this.#id = id;\n this.inner = inner;\n }\n\n setInner(newInner: T) {\n this.inner = newInner;\n }\n\n get id() {\n return this.#id;\n }\n\n move(x: number, y: number) {\n this.position.set(x, y);\n for (const cb of this.#onMove) {\n cb(this.position);\n }\n }\n\n onMove(cb: (pos: Vec2) => void) {\n this.#onMove.push(cb);\n return () => {\n this.#onMove = this.#onMove.filter((c) => c !== cb);\n };\n }\n}\n\n/** A group of entities */\nexport class Group {\n #id: number;\n name: string;\n entities: Set<number> = new Set();\n groups: Set<number> = new Set();\n position: Vec2 = new Vec2();\n parentId: number | null = null;\n\n constructor(id: number, name: string = '') {\n this.#id = id;\n this.name = name;\n }\n\n get id() {\n return this.#id;\n }\n\n add(entityId: number) {\n this.entities.add(entityId);\n }\n\n remove(entityId: number) {\n this.entities.delete(entityId);\n }\n\n addGroup(groupId: number) {\n this.groups.add(groupId);\n }\n\n removeGroup(groupId: number) {\n this.groups.delete(groupId);\n }\n}\n\nexport enum LinkKind {\n LINE = 'LINE',\n STEP = 'STEP',\n SMOOTH_STEP = 'SMOOTH_STEP',\n BEZIER = 'BEZIER'\n}\n\n/** A connection between sockets */\nexport class Link<T = any> {\n #id: number;\n from: number; // Socket ID\n to: number; // Socket ID\n kind: LinkKind;\n waypoints: Vec2[] = [];\n inner: T;\n\n constructor(id: number, from: number, to: number, kind = LinkKind.LINE, inner: T = {} as T) {\n this.#id = id;\n this.from = from;\n this.to = to;\n this.kind = kind;\n this.inner = inner;\n }\n\n get id() {\n return this.#id;\n }\n}\n"],"mappings":";AAAA,IAAa,OAAb,MAAa,KAAK;CAChB,YACE,AAAO,IAAY,GACnB,AAAO,IAAY,GACnB;EAFO;EACA;;CAGT,IAAI,GAAW,GAAW;AACxB,OAAK,IAAI;AACT,OAAK,IAAI;AACT,SAAO;;CAGT,KAAK,OAAa;AAChB,OAAK,IAAI,MAAM;AACf,OAAK,IAAI,MAAM;AACf,SAAO;;CAGT,QAAQ;AACN,SAAO,IAAI,KAAK,KAAK,GAAG,KAAK,EAAE;;;AAInC,IAAY,kDAAL;AACL;AACA;;;;AAIF,IAAa,SAAb,MAAoB;CAClB;CACA;CACA;CACA;CACA,SAAe,IAAI,MAAM;CACzB,QAAa;CAEb,YAAY,IAAY,UAAkB,MAAkB,OAAe,IAAI;AAC7E,QAAKA,KAAM;AACX,OAAK,WAAW;AAChB,OAAK,OAAO;AACZ,OAAK,OAAO;;CAGd,IAAI,KAAK;AACP,SAAO,MAAKA;;;;AAKhB,IAAa,SAAb,MAA6B;CAC3B;CACA,WAAiB,IAAI,MAAM;CAC3B,0BAA+B,IAAI,KAAK;CACxC;CACA,UAAmC,EAAE;CACrC,WAA0B;CAE1B,YAAY,IAAY,OAAU;AAChC,QAAKA,KAAM;AACX,OAAK,QAAQ;;CAGf,SAAS,UAAa;AACpB,OAAK,QAAQ;;CAGf,IAAI,KAAK;AACP,SAAO,MAAKA;;CAGd,KAAK,GAAW,GAAW;AACzB,OAAK,SAAS,IAAI,GAAG,EAAE;AACvB,OAAK,MAAM,MAAM,MAAKC,OACpB,IAAG,KAAK,SAAS;;CAIrB,OAAO,IAAyB;AAC9B,QAAKA,OAAQ,KAAK,GAAG;AACrB,eAAa;AACX,SAAKA,SAAU,MAAKA,OAAQ,QAAQ,MAAM,MAAM,GAAG;;;;;AAMzD,IAAa,QAAb,MAAmB;CACjB;CACA;CACA,2BAAwB,IAAI,KAAK;CACjC,yBAAsB,IAAI,KAAK;CAC/B,WAAiB,IAAI,MAAM;CAC3B,WAA0B;CAE1B,YAAY,IAAY,OAAe,IAAI;AACzC,QAAKD,KAAM;AACX,OAAK,OAAO;;CAGd,IAAI,KAAK;AACP,SAAO,MAAKA;;CAGd,IAAI,UAAkB;AACpB,OAAK,SAAS,IAAI,SAAS;;CAG7B,OAAO,UAAkB;AACvB,OAAK,SAAS,OAAO,SAAS;;CAGhC,SAAS,SAAiB;AACxB,OAAK,OAAO,IAAI,QAAQ;;CAG1B,YAAY,SAAiB;AAC3B,OAAK,OAAO,OAAO,QAAQ;;;AAI/B,IAAY,8CAAL;AACL;AACA;AACA;AACA;;;;AAIF,IAAa,OAAb,MAA2B;CACzB;CACA;CACA;CACA;CACA,YAAoB,EAAE;CACtB;CAEA,YAAY,IAAY,MAAc,IAAY,OAAO,SAAS,MAAM,QAAW,EAAE,EAAO;AAC1F,QAAKA,KAAM;AACX,OAAK,OAAO;AACZ,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,QAAQ;;CAGf,IAAI,KAAK;AACP,SAAO,MAAKA"}
@@ -0,0 +1,132 @@
1
+ import { LinkKind, SocketKind } from "./elements.js";
2
+
3
+ //#region src/core/history.d.ts
4
+ type HistoryAction = {
5
+ type: 'MOVE_ENTITY';
6
+ id: number;
7
+ from: {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ to: {
12
+ x: number;
13
+ y: number;
14
+ };
15
+ } | {
16
+ type: 'MOVE_GROUP';
17
+ id: number;
18
+ from: {
19
+ x: number;
20
+ y: number;
21
+ };
22
+ to: {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ } | {
27
+ type: 'CREATE_ENTITY';
28
+ id: number;
29
+ inner: any;
30
+ position: {
31
+ x: number;
32
+ y: number;
33
+ };
34
+ parentId: number | null;
35
+ } | {
36
+ type: 'DROP_ENTITY';
37
+ id: number;
38
+ inner: any;
39
+ position: {
40
+ x: number;
41
+ y: number;
42
+ };
43
+ parentId: number | null;
44
+ } | {
45
+ type: 'CREATE_LINK';
46
+ id: number;
47
+ from: number;
48
+ to: number;
49
+ kind: LinkKind;
50
+ inner?: any;
51
+ } | {
52
+ type: 'DROP_LINK';
53
+ id: number;
54
+ from: number;
55
+ to: number;
56
+ kind: LinkKind;
57
+ inner?: any;
58
+ } | {
59
+ type: 'UPDATE_LINK';
60
+ id: number;
61
+ from: {
62
+ old: number;
63
+ new: number;
64
+ };
65
+ to: {
66
+ old: number;
67
+ new: number;
68
+ };
69
+ waypoints?: {
70
+ old: {
71
+ x: number;
72
+ y: number;
73
+ }[];
74
+ new: {
75
+ x: number;
76
+ y: number;
77
+ }[];
78
+ };
79
+ } | {
80
+ type: 'ADD_TO_GROUP';
81
+ groupId: number;
82
+ entityId: number;
83
+ oldParentId: number | null;
84
+ } | {
85
+ type: 'REMOVE_FROM_GROUP';
86
+ groupId: number;
87
+ entityId: number;
88
+ oldParentId: number | null;
89
+ } | {
90
+ type: 'CREATE_SOCKET';
91
+ id: number;
92
+ entityId: number;
93
+ kind: SocketKind;
94
+ name: string;
95
+ offset: {
96
+ x: number;
97
+ y: number;
98
+ };
99
+ } | {
100
+ type: 'DROP_SOCKET';
101
+ id: number;
102
+ entityId: number;
103
+ kind: SocketKind;
104
+ name: string;
105
+ offset: {
106
+ x: number;
107
+ y: number;
108
+ };
109
+ } | {
110
+ type: 'FROM_JSON';
111
+ data: any;
112
+ };
113
+ interface Command {
114
+ do: HistoryAction[];
115
+ undo: HistoryAction[];
116
+ label?: string;
117
+ timestamp: number;
118
+ }
119
+ declare class HistoryManager {
120
+ undoStack: Command[];
121
+ redoStack: Command[];
122
+ private maxHistory;
123
+ push(command: Command): void;
124
+ toJSON(): {
125
+ undoStack: Command[];
126
+ redoStack: Command[];
127
+ };
128
+ fromJSON(data: any): void;
129
+ }
130
+ //#endregion
131
+ export { HistoryAction, HistoryManager };
132
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","names":[],"sources":["../../src/core/history.ts"],"mappings":";;;KAEY,aAAA;EAEN,IAAA;EACA,EAAA;EACA,IAAA;IAAQ,CAAA;IAAW,CAAA;EAAA;EACnB,EAAA;IAAM,CAAA;IAAW,CAAA;EAAA;AAAA;EAEjB,IAAA;EAAoB,EAAA;EAAY,IAAA;IAAQ,CAAA;IAAW,CAAA;EAAA;EAAa,EAAA;IAAM,CAAA;IAAW,CAAA;EAAA;AAAA;EAEjF,IAAA;EACA,EAAA;EACA,KAAA;EACA,QAAA;IAAY,CAAA;IAAW,CAAA;EAAA;EACvB,QAAA;AAAA;EAGA,IAAA;EACA,EAAA;EACA,KAAA;EACA,QAAA;IAAY,CAAA;IAAW,CAAA;EAAA;EACvB,QAAA;AAAA;EAGA,IAAA;EACA,EAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA,EAAM,QAAA;EACN,KAAA;AAAA;EAGA,IAAA;EACA,EAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA,EAAM,QAAA;EACN,KAAA;AAAA;EAGA,IAAA;EACA,EAAA;EACA,IAAA;IAAQ,GAAA;IAAa,GAAA;EAAA;EACrB,EAAA;IAAM,GAAA;IAAa,GAAA;EAAA;EACnB,SAAA;IAAc,GAAA;MAAO,CAAA;MAAW,CAAA;IAAA;IAAe,GAAA;MAAO,CAAA;MAAW,CAAA;IAAA;EAAA;AAAA;EAEjE,IAAA;EAAsB,OAAA;EAAiB,QAAA;EAAkB,WAAA;AAAA;EACzD,IAAA;EAA2B,OAAA;EAAiB,QAAA;EAAkB,WAAA;AAAA;EAE9D,IAAA;EACA,EAAA;EACA,QAAA;EACA,IAAA,EAAM,UAAA;EACN,IAAA;EACA,MAAA;IAAU,CAAA;IAAW,CAAA;EAAA;AAAA;EAGrB,IAAA;EACA,EAAA;EACA,QAAA;EACA,IAAA,EAAM,UAAA;EACN,IAAA;EACA,MAAA;IAAU,CAAA;IAAW,CAAA;EAAA;AAAA;EAErB,IAAA;EAAmB,IAAA;AAAA;AAAA,UAER,OAAA;EACf,EAAA,EAAI,aAAA;EACJ,IAAA,EAAM,aAAA;EACN,KAAA;EACA,SAAA;AAAA;AAAA,cAGW,cAAA;EACX,SAAA,EAAW,OAAA;EACX,SAAA,EAAW,OAAA;EAAA,QACH,UAAA;EAER,IAAA,CAAK,OAAA,EAAS,OAAA;EAQd,MAAA,CAAA;;;;EAOA,QAAA,CAAS,IAAA;AAAA"}
@@ -0,0 +1,25 @@
1
+ //#region src/core/history.ts
2
+ var HistoryManager = class {
3
+ undoStack = [];
4
+ redoStack = [];
5
+ maxHistory = 100;
6
+ push(command) {
7
+ this.undoStack.push(command);
8
+ this.redoStack = [];
9
+ if (this.undoStack.length > this.maxHistory) this.undoStack.shift();
10
+ }
11
+ toJSON() {
12
+ return {
13
+ undoStack: this.undoStack,
14
+ redoStack: this.redoStack
15
+ };
16
+ }
17
+ fromJSON(data) {
18
+ this.undoStack = data.undoStack || [];
19
+ this.redoStack = data.redoStack || [];
20
+ }
21
+ };
22
+
23
+ //#endregion
24
+ export { HistoryManager };
25
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","names":[],"sources":["../../src/core/history.ts"],"sourcesContent":["import { LinkKind, SocketKind } from './elements';\n\nexport type HistoryAction =\n | {\n type: 'MOVE_ENTITY';\n id: number;\n from: { x: number; y: number };\n to: { x: number; y: number };\n }\n | { type: 'MOVE_GROUP'; id: number; from: { x: number; y: number }; to: { x: number; y: number } }\n | {\n type: 'CREATE_ENTITY';\n id: number;\n inner: any;\n position: { x: number; y: number };\n parentId: number | null;\n }\n | {\n type: 'DROP_ENTITY';\n id: number;\n inner: any;\n position: { x: number; y: number };\n parentId: number | null;\n }\n | {\n type: 'CREATE_LINK';\n id: number;\n from: number;\n to: number;\n kind: LinkKind;\n inner?: any;\n }\n | {\n type: 'DROP_LINK';\n id: number;\n from: number;\n to: number;\n kind: LinkKind;\n inner?: any;\n }\n | {\n type: 'UPDATE_LINK';\n id: number;\n from: { old: number; new: number };\n to: { old: number; new: number };\n waypoints?: { old: { x: number; y: number }[]; new: { x: number; y: number }[] };\n }\n | { type: 'ADD_TO_GROUP'; groupId: number; entityId: number; oldParentId: number | null }\n | { type: 'REMOVE_FROM_GROUP'; groupId: number; entityId: number; oldParentId: number | null }\n | {\n type: 'CREATE_SOCKET';\n id: number;\n entityId: number;\n kind: SocketKind;\n name: string;\n offset: { x: number; y: number };\n }\n | {\n type: 'DROP_SOCKET';\n id: number;\n entityId: number;\n kind: SocketKind;\n name: string;\n offset: { x: number; y: number };\n }\n | { type: 'FROM_JSON'; data: any };\n\nexport interface Command {\n do: HistoryAction[];\n undo: HistoryAction[];\n label?: string;\n timestamp: number;\n}\n\nexport class HistoryManager {\n undoStack: Command[] = [];\n redoStack: Command[] = [];\n private maxHistory: number = 100;\n\n push(command: Command) {\n this.undoStack.push(command);\n this.redoStack = [];\n if (this.undoStack.length > this.maxHistory) {\n this.undoStack.shift();\n }\n }\n\n toJSON() {\n return {\n undoStack: this.undoStack,\n redoStack: this.redoStack\n };\n }\n\n fromJSON(data: any) {\n this.undoStack = data.undoStack || [];\n this.redoStack = data.redoStack || [];\n }\n}\n"],"mappings":";AA0EA,IAAa,iBAAb,MAA4B;CAC1B,YAAuB,EAAE;CACzB,YAAuB,EAAE;CACzB,AAAQ,aAAqB;CAE7B,KAAK,SAAkB;AACrB,OAAK,UAAU,KAAK,QAAQ;AAC5B,OAAK,YAAY,EAAE;AACnB,MAAI,KAAK,UAAU,SAAS,KAAK,WAC/B,MAAK,UAAU,OAAO;;CAI1B,SAAS;AACP,SAAO;GACL,WAAW,KAAK;GAChB,WAAW,KAAK;GACjB;;CAGH,SAAS,MAAW;AAClB,OAAK,YAAY,KAAK,aAAa,EAAE;AACrC,OAAK,YAAY,KAAK,aAAa,EAAE"}
@@ -0,0 +1,37 @@
1
+ import { Link, Vec2 } from "./elements.js";
2
+ import { Context } from "./context.js";
3
+
4
+ //#region src/core/layout.d.ts
5
+ declare function getLinkPoints(ctx: Context, link: Link): {
6
+ from: Vec2;
7
+ to: Vec2;
8
+ } | null;
9
+ declare function getLinkCenter(ctx: Context, link: Link): Vec2 | null;
10
+ declare function getLinkPath(ctx: Context, link: Link): string | null;
11
+ declare class Rect {
12
+ x: number;
13
+ y: number;
14
+ w: number;
15
+ h: number;
16
+ constructor(x: number, y: number, w: number, h: number);
17
+ contains(point: Vec2): boolean;
18
+ intersects(range: Rect): boolean;
19
+ }
20
+ declare class QuadTree<T> {
21
+ boundary: Rect;
22
+ private capacity;
23
+ private points;
24
+ private divided;
25
+ private northwest;
26
+ private northeast;
27
+ private southwest;
28
+ private southeast;
29
+ constructor(boundary: Rect);
30
+ subdivide(): void;
31
+ insert(pos: Vec2, data: T): boolean;
32
+ query(range: Rect, found?: T[]): T[];
33
+ clear(): void;
34
+ }
35
+ //#endregion
36
+ export { QuadTree, Rect, getLinkCenter, getLinkPath, getLinkPoints };
37
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","names":[],"sources":["../../src/core/layout.ts"],"mappings":";;;;iBAGgB,aAAA,CAAc,GAAA,EAAK,OAAA,EAAS,IAAA,EAAM,IAAA;EAAS,IAAA,EAAM,IAAA;EAAM,EAAA,EAAI,IAAA;AAAA;AAAA,iBAsB3D,aAAA,CAAc,GAAA,EAAK,OAAA,EAAS,IAAA,EAAM,IAAA,GAAO,IAAA;AAAA,iBAczC,WAAA,CAAY,GAAA,EAAK,OAAA,EAAS,IAAA,EAAM,IAAA;AAAA,cAsEnC,IAAA;EAEF,CAAA;EACA,CAAA;EACA,CAAA;EACA,CAAA;cAHA,CAAA,UACA,CAAA,UACA,CAAA,UACA,CAAA;EAGT,QAAA,CAAS,KAAA,EAAO,IAAA;EAShB,UAAA,CAAW,KAAA,EAAO,IAAA;AAAA;AAAA,cAUP,QAAA;EAUQ,QAAA,EAAU,IAAA;EAAA,QATrB,QAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EAAA,QAEA,SAAA;EAAA,QACA,SAAA;EAAA,QACA,SAAA;EAAA,QACA,SAAA;cAEW,QAAA,EAAU,IAAA;EAE7B,SAAA,CAAA;EAeA,MAAA,CAAO,GAAA,EAAK,IAAA,EAAM,IAAA,EAAM,CAAA;EAsBxB,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM,KAAA,GAAO,CAAA,KAAW,CAAA;EAqBrC,KAAA,CAAA;AAAA"}