SOLVED Constrain to angles other than 0, 90, 45.
-
Hey there!
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.
-
Its indeed similar to a pen. This allows easy subclassing of internal tools by simply adding behaviour to a tool.
This tool is subclassing
_mouseDragged
as it needs the same behaviour but with the shift constrain disabled, as this tool will perform his own shift behaviour.
-
hello @colinmford,
that part was done by @frederik. if I understand it correctly,
_mouseDragged
is the internal method provided by theBaseEventTool
superclass, which is called externally by themouseDragged
method in theEditingTool
class that inherits from it. in this case, we’re modifying the internal behavior.it’s a bit like the
_moveTo
andmoveTo
methods in a BasePen…I hope this is correct and makes sense!
-
@gferreira why
_mouseDragged
instead ofmouseDragged
?
-
@gferreira @frederik Oh wow! Thanks so so much!
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.
-
hello @ro-hernandezz,
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[0] # 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!
-
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! :)