Skip to content

Instantly share code, notes, and snippets.

@typesupply
Last active September 21, 2023 16:20
Show Gist options
  • Save typesupply/09bdae70d41caa81ace6318ceb19fed2 to your computer and use it in GitHub Desktop.
Save typesupply/09bdae70d41caa81ace6318ceb19fed2 to your computer and use it in GitHub Desktop.
Test Merz hit testing with a glyph editor.
from mojo.events import BaseEventTool, installTool
backgroundColor = (1, 1, 0, 0.5)
mouseDownColor = (0, 0, 0, 0.25)
defaultSymbolSettings = dict(
name="oval",
size=(20, 20),
fillColor=(1, 0, 0, 0.75),
strokeColor=(1, 1, 1, 0.5),
strokeWidth=10
)
"""
Hit Reporting:
intersects rect: black stroke
contained by rect: square
contains point: green
"""
class MerzHitTestTool(BaseEventTool):
def setup(self):
self.container = self.extensionContainer(
identifier="com.typesupply.merzHitTestTest",
location="foreground",
clear=True
)
self.pointContainer = self.container.appendBaseSublayer(
position=(0, 0),
size=(0, 0),
backgroundColor=backgroundColor,
visible=True
)
self.mouseDownRect = self.container.appendBaseSublayer(
position=(0, 0),
size=(0, 0),
backgroundColor=mouseDownColor,
visible=False,
acceptsHit=False
)
def updateDisplay(self):
self.glyph = self.getGlyph()
bounds = self.glyph.bounds
if bounds is None:
self.pointContainer.setVisible(False)
return
xMin, yMin, xMax, yMax = bounds
width = xMax - xMin
height = yMax - yMin
with self.pointContainer.propertyGroup():
self.pointContainer.setPosition((xMin, yMin))
self.pointContainer.setSize((width, height))
self.pointContainer.setVisible(True)
xLocations = [width * (i * 0.1) for i in range(11)]
yLocations = [height * (i * 0.1) for i in range(11)]
with self.pointContainer.sublayerGroup():
for x in xLocations:
for y in yLocations:
self.pointContainer.appendSymbolSublayer(
name=f"symbol-{int(x)}-{int(y)}",
position=(x, y),
imageSettings=defaultSymbolSettings,
acceptsHit=True
)
def becomeActive(self):
self.updateDisplay()
def becomeInactive(self):
self.pointContainer.setVisible(False)
def hitTest(self, point):
# draw the selection rect
x, y = point
rect = (x - 50, y - 50, 100, 100)
with self.mouseDownRect.propertyGroup():
self.mouseDownRect.setPosition(rect[:2])
self.mouseDownRect.setSize(rect[2:])
self.mouseDownRect.setVisible(True)
# reset all to the default state
for layer in self.pointContainer.getSublayers():
layer.setImageSettings(defaultSymbolSettings)
# test: contained by rect
hits = self.container.findSublayersContainedByRect(
rect,
onlyAcceptsHit=True,
recurse=True
)
for layer in hits:
imageSettings = dict(layer.getImageSettings())
imageSettings["name"] = "rectangle"
layer.setImageSettings(imageSettings)
# test: intersected by rect
hits = self.container.findSublayersIntersectedByRect(
rect,
onlyAcceptsHit=True,
recurse=True
)
for layer in hits:
imageSettings = dict(layer.getImageSettings())
imageSettings["strokeColor"] = (0, 0, 0, 0.5)
layer.setImageSettings(imageSettings)
# test: contains point
hits = self.container.findSublayersContainingPoint(
point,
onlyAcceptsHit=True,
recurse=True
)
for layer in hits:
imageSettings = dict(layer.getImageSettings())
imageSettings["fillColor"] = (0, 1, 0, 0.75)
layer.setImageSettings(imageSettings)
def mouseDown(self, point, clickCount):
self.hitTest(point)
def mouseDragged(self, point, delta):
self.hitTest(point)
def mouseUp(self, point):
self.mouseDownRect.setVisible(False)
for layer in self.pointContainer.getSublayers():
layer.setImageSettings(defaultSymbolSettings)
def getToolbarTip(self):
return "Merz Hit Test Test"
def viewDidChangeGlyph(self):
self.updateDisplay()
if __name__ == '__main__':
tool = MerzHitTestTool()
installTool(tool)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment