Constrain to angles other than 0, 90, 45.
ro-hernandezz last edited by gferreira
I'm drawing a weird slanted thing with angled extremes and it's getting annoying to align everything by hand to guidelines.
So I was wondering if there's already a tool to constrain handles to an arbitrary angle (other than horizontal, vertical and 45º).
Thought I'd ask before I dive into trying to write one myself.
I dont know of such a tool... and the current EditingTool has 0°, 90° and optionally 45° backed in.
Maybe RF should add the italic angle as an optional constrain. I remember testing multiple constrains but it didnt work out good (I dont know why, probably to complex from the users point of view)
But a single tool with a single constrain is not that hard! :)
here’s a custom editing tool which uses the font’s italic angle to constrain point movements. it’s actually very useful!
from math import tan, radians from mojo.events import EditingTool, installTool from defcon import Point class ConstrainAngleEditingTool(EditingTool): def getToolbarTip(self): return "Constrain Angle" def modifyDeltaForAngle(self, delta, angle): '''Constrain delta to a given angle.''' _tan1 = tan(radians(angle + 90)) _tan2 = tan(radians(angle)) if abs(_tan1) < abs(_tan2): delta.x = -_tan1 * delta.y else: delta.y = _tan2 * delta.x def modifyDraggingPoint(self, point, delta): '''Constrain on-curve points to italic angle.''' # get italic angle from font! f = CurrentFont() self.angle = f.info.italicAngle - 90 # calculate delta for current mouse down point if self.mouseDownPoints: fx, fy = self.mouseDownPoints[-1] else: fx, fy = point delta.x = point.x - fx delta.y = point.y - fy # constrain delta to angle if self.shiftDown: self.modifyDeltaForAngle(delta, self.angle) return point, delta def _mouseDragged(self, point, delta): '''Constrain off-curve points to italic angle.''' # apply default _mouseDragged behavior first shiftdown = self.shiftDown self.shiftDown = False super()._mouseDragged(point, delta) self.shiftDown = shiftdown # handle single off-curve point selection if self.shiftDown and self.selection.containsSingleOffCurve(): # get selected off-curve point offcurve = self.selection.selectedPoints # get related on-curve point info = self.selection.selectionDataForPoint(offcurve) anchor = info["anchor"] # calculate delta for off-curve point offcurveDelta = Point((offcurve.x - anchor.x, offcurve.y - anchor.y)) # constrain delta to angle self.modifyDeltaForAngle(offcurveDelta, self.angle) # update position of off-curve point offcurve.x = anchor.x + offcurveDelta.x offcurve.y = anchor.y + offcurveDelta.y installTool(ConstrainAngleEditingTool())
handling off-curve points was a bit harder because they are constrained in relation to their on-curve point, not the last mouse down point. thanks @frederik for showing how to do it.
have fun drawing weird slanted things!
ro-hernandezz last edited by
I was wondering how to write such a thing since I've never done an interactive tool, but my timeline seems to go much slower than Gustavo's!
It seems I wasn't totally lost, but would've got stuck in sooo many places.
Thanks again! I will def use this a lot.
colinmford last edited by gferreira
that part was done by @frederik. if I understand it correctly,
_mouseDraggedis the internal method provided by the
BaseEventToolsuperclass, which is called externally by the
mouseDraggedmethod in the
EditingToolclass that inherits from it. in this case, we’re modifying the internal behavior.
it’s a bit like the
moveTomethods in a BasePen…
I hope this is correct and makes sense!
Its indeed similar to a pen. This allows easy subclassing of internal tools by simply adding behaviour to a tool.
This tool is subclassing
_mouseDraggedas it needs the same behaviour but with the shift constrain disabled, as this tool will perform his own shift behaviour.