class SelfConnection { constructor(state, mouse) { this.id = guid(); this.state = state; this.anchorAngle = 0; this.mouseOffsetAngle = 0; this._text = ''; if(mouse) { this.setAnchorPoint(mouse.x, mouse.y); } } get text() { return this._text; } set text(value) { documents[activeDocument].addChange('selfconnection', this.id, 'edit', ['_text'], [this._text], true); this._text = value; documents[activeDocument].addChange('selfconnection', this.id, 'edit', ['_text'], [this._text]); } setMouseStart(x, y) { this.mouseOffsetAngle = this.anchorAngle - Math.atan2(y - this.state.y, x - this.state.x); } setAnchorPoint(x, y) { this.anchorAngle = Math.atan2(y - this.state.y, x - this.state.x) + this.mouseOffsetAngle; const snap = Math.round(this.anchorAngle / (Math.PI / 2)) * (Math.PI / 2); if(Math.abs(this.anchorAngle - snap) < .1) this.anchorAngle = snap; if(this.anchorAngle < -Math.PI) this.anchorAngle += 2 * Math.PI; if(this.anchorAngle > Math.PI) this.anchorAngle -= 2 * Math.PI; } getEndPointsAndCircle() { const circle = { x: this.state.x + 1.5 * radius * Math.cos(this.anchorAngle), y: this.state.y + 1.5 * radius * Math.sin(this.anchorAngle), radius: 0.75 * radius, }; const startAngle = this.anchorAngle - Math.PI * .8; const endAngle = this.anchorAngle + Math.PI * .8; const start = { x: circle.x + circle.radius * Math.cos(startAngle), y: circle.y + circle.radius * Math.sin(startAngle), }; const end = { x: circle.x + circle.radius * Math.cos(endAngle), y: circle.y + circle.radius * Math.sin(endAngle), }; return { isCircle: true, start, end, startAngle, endAngle, circle, }; } draw() { const endPoints = this.getEndPointsAndCircle(); ctx.strokeStyle = ctx.fillStyle = settings.colors.getColor(this); ctx.beginPath(); ctx.arc(endPoints.circle.x, endPoints.circle.y, endPoints.circle.radius, endPoints.startAngle, endPoints.endAngle); ctx.stroke(); ctx.closePath(); const textX = endPoints.circle.x + endPoints.circle.radius * Math.cos(this.anchorAngle), textY = endPoints.circle.y + endPoints.circle.radius * Math.sin(this.anchorAngle); ctx.drawText(this.text, textX, textY, this.anchorAngle, selectedObject === this); ctx.drawArrow(endPoints.end.x, endPoints.end.y, endPoints.endAngle + Math.PI * .4); } containsPoint(x, y) { const endPoints = this.getEndPointsAndCircle(), dx = x - endPoints.circle.x, dy = y - endPoints.circle.y, distance = Math.sqrt(dx ** 2 + dy ** 2) - endPoints.circle.radius; return Math.abs(distance) < settings.hitTargetPadding; } }