First script in my life = first problem with scripting

Hi
This is my first script for creating inktraps(also this is my first try in programming).
For this experiment I removed overlap in whole glyph “m” and created component _corner.corner with anchor on “zero” X-Y position.

import math
#calcAngle counts Angle between two lines
def calcAngle(lineA,lineB): 
	line1Y1 = lineA[0][1]
	line1X1 = lineA[0][0]
	line1Y2 = lineA[1][1]
	line1X2 = lineA[1][0]

	line2Y1 = lineB[0][1]
	line2X1 = lineB[0][0]
	line2Y2 = lineB[1][1]
	line2X2 = lineB[1][0]

	angle1 = math.atan2(line1Y1-line1Y2,line1X1-line1X2)
	angle2 = math.atan2(line2Y1-line2Y2,line2X1-line2X2)
	angleDegree = (angle1-angle2) * 360 / (2*math.pi)
	return angleDegree

layer = Glyphs.font.selectedLayers[0]

nodeList = layer.paths[0].nodes 

nodeListToSelect = []

#loop which check every angle
for index in range(len(nodeList)):
	nodeLeft = nodeList[index]
	nodeMiddle = nodeList[index+1]
	nodeRight = nodeList[index+2]
	lineA = ((nodeMiddle.x,nodeMiddle.y),(nodeLeft.x,nodeLeft.y))
	lineB = ((nodeMiddle.x,nodeMiddle.y),(nodeRight.x,nodeRight.y))
	angle = calcAngle(lineA, lineB)

	if angle < 0:
		angle = angle * -1

	if angle <= 45:
		nodeListToSelect.append(nodeMiddle)
	
#adding component
layer.components.append(GSComponent('_corner.corner', NSPoint(nodeListToSelect[0].x, nodeListToSelect[0].y)))

after running script I’m getting this:

Traceback (most recent call last):
  File "<string>", line 47, in <module>
NameError: name 'NSPoint' is not defined

Maybe I didn’t get how to use documentation?
Please. help me
//sorry for my english: I have a little hangover

and i don’t know if this way of adding component will work with super-duper-corner components.
Cheers

from

 layer.components.append(GSComponent('_corner.corner', NSPoint(nodeListToSelect[0].x, nodeListToSelect[0].y)))

I just deleted “NSPoint”.
Everything is great except my script treats corner component as regular. Any advice?

I wonder if the NSPoint problem is this: Python scripts not working (807)

Try from Foundation import NSPoint.

Corner components are not actually components. They are implemented as hints. I’ll post some sample code, soon.

Great, thanks

Thanks Simon!
I imported NSPoint. And it works without problems, but the script still doesn’t treat component as a corner. I will wait for Georg’s samples.
What’s more interesting: it looks the same as when I didn’t use NSPoint.

from Foundation import NSMutableOrderedSet
l = Font.selectedLayers[0]
if len(l.selection) == 1 and isinstance(l.selection[0], GSNode):
	
	Corner = GSHint.alloc().init()
	Corner.type = CORNER
	Corner.setName_("_corner.test")
	Corner.originNode = l.selection[0]
	print Corner
	l.hints.append(Corner)
	l.clearSelection()

Thanks a lot Georg, works fine.

I have a problem: After using this script I can’t turn back by hitting command+z. Any advice?
Now script looks like this:

import math
#This script needs corner-component called "_corner.inktrap" to work
def calcAngle(lineA,lineB): 

	line1Y1 = lineA[0][1]
	line1X1 = lineA[0][0]
	line1Y2 = lineA[1][1]
	line1X2 = lineA[1][0]

	line2Y1 = lineB[0][1]
	line2X1 = lineB[0][0]
	line2Y2 = lineB[1][1]
	line2X2 = lineB[1][0]

	
	angle1 = math.atan2(line1Y1-line1Y2,line1X1-line1X2)
	angle2 = math.atan2(line2Y1-line2Y2,line2X1-line2X2)
	angleDegree = (angle1-angle2) * 360 / (2*math.pi)
	return angleDegree

layer = Glyphs.font.selectedLayers[0] 
layer.removeOverlap()

nodeList = layer.paths[0].nodes #wejscie przez scierzki "paths" do jej wszystkich nodesow w formie listy
 
nodeListToSelect = []

for index in range(len(nodeList)):
	nodeLeft = nodeList[index]
	nodeMiddle = nodeList[index+1]
	nodeRight = nodeList[index+2]
	lineA = ((nodeMiddle.x,nodeMiddle.y),(nodeLeft.x,nodeLeft.y))
	lineB = ((nodeMiddle.x,nodeMiddle.y),(nodeRight.x,nodeRight.y))
	angle = calcAngle(lineA, lineB)

	if angle < 0:
		angle = angle * -1
	
	if angle <= 50:
		nodeListToSelect.append(nodeMiddle)

print nodeListToSelect

for index in range(len(nodeListToSelect)):
	

	Corner = GSHint.alloc().init()
	Corner.type = CORNER
	Corner.setName_("_corner.inktrap")
	Corner.originNode = nodeListToSelect[index]
	layer.hints.append(Corner)

Have you tried to use beginUndo() and endUndo() ?
http://docu.glyphsapp.com/#beginUndo

No. thanks a lot. Dummy’s omission

Crashes when pressing command+z: I’m doing something wrong :frowning:

import math
#skrypt potrzebuje componentu _corner.corner, w ktorym jest narysowany inktrap
def calcAngle(lineA,lineB): 

	line1Y1 = lineA[0][1]
	line1X1 = lineA[0][0]
	line1Y2 = lineA[1][1]
	line1X2 = lineA[1][0]

	line2Y1 = lineB[0][1]
	line2X1 = lineB[0][0]
	line2Y2 = lineB[1][1]
	line2X2 = lineB[1][0]

	#oblicza kat mixedzy dwoma prostymi
	angle1 = math.atan2(line1Y1-line1Y2,line1X1-line1X2)
	angle2 = math.atan2(line2Y1-line2Y2,line2X1-line2X2)
	angleDegree = (angle1-angle2) * 360 / (2*math.pi)
	return angleDegree

layer = Glyphs.font.selectedLayers[0] #wejscie w layer zaznaczonej litery, tak na prawde ne potrzebne w tym wypadku, gdyz layer juz zostalo w AP przypisane glownemu layer-masterowi glyph'u(np. regular-layer). za pomoca tego, co tu utworzono mozna sie dostawac do layerow pobocznych.

layer.removeOverlap()

nodeList = layer.paths[0].nodes #wejscie przez scierzki "paths" do jej wszystkich nodesow w formie listy
 
nodeListToSelect = []

#petla, ktora jako powtorzenie dowiaduje sie wspolrzednych trzech kolejnych po sobie punktow(tak przez cala scierzke)
#jej zadaniem jest obliczenie kata, ktorego wierzcholkiem jest punkt nodeMiddle, 
#a jego ramiona przecinaja punkty: nodeLeft oraz nodeRight.
for index in range(len(nodeList)):
	nodeLeft = nodeList[index]
	nodeMiddle = nodeList[index+1]
	nodeRight = nodeList[index+2]
	lineA = ((nodeMiddle.x,nodeMiddle.y),(nodeLeft.x,nodeLeft.y))
	lineB = ((nodeMiddle.x,nodeMiddle.y),(nodeRight.x,nodeRight.y))
	angle = calcAngle(lineA, lineB)

	if angle < 0:
		angle = angle * -1
	
	if angle <= 45:
		nodeListToSelect.append(nodeMiddle)

print nodeListToSelect

for index in range(len(nodeListToSelect)):
	#layer.components.append(GSComponent('_corner.corner', (nodeListToSelect[index].x, nodeListToSelect[index].y)))
	

	Corner = GSHint.alloc().init()
	Corner.type = CORNER
	Corner.setName_("_corner.corner")
	Corner.originNode = nodeListToSelect[index]
	layer.hints.append(Corner)

for thisLayer in listOfSelectedLayers:
	thisGlyph = thisLayer.parent
	thisGlyph.beginUndo() # begin undo grouping
	thisGlyph.name
	unRound( thisLayer )
	thisGlyph.endUndo()   # end undo grouping

Another, maybe stupid question: I tried to search in documentation, but didn’t find it(maybe I don’t understand everything correctly):
How can I affect changes(for example with little “flipping” script showed below) in all masters at once? In this script I can only flip letter in active layer (selectedLayer). I did’n find a solution.
Thanks in advance

#MenuTitle: flipper
# -*- coding: utf-8 -*-
__doc__="""script flips glyphs"""

myMaster = Glyphs.font.selectedFontMaster
totalHeight = myMaster.xHeight
myLetters = Glyphs.font.selectedLayers

#counting x of middle point

allXnodes = []
for myLetter in myLetters:
	
	myPaths = myLetter.paths
	
	for myPath in myPaths:  
		for myNodes in myPath.nodes:
				allXnodes.append(myNodes.x)	
	
minXvalue = min(allXnodes)

maxXvalue = max(allXnodes)
#This is x value of mille point:
middlePointX = maxXvalue - (maxXvalue - minXvalue)/2


myMaster = Glyphs.font.selectedFontMaster
totalHeight = myMaster.xHeight
myLetters = Glyphs.font.selectedLayers

#counting y of middle point

allYnodes = []
for myLetter in myLetters:
	
	myPaths = myLetter.paths
	
	for myPath in myPaths:  
		for myNodes in myPath.nodes:
				allYnodes.append(myNodes.y)	
	
minYvalue = min(allYnodes)

maxYvalue = max(allYnodes)
#This is y value of mille point:
middlePointY = maxYvalue - (maxYvalue - minYvalue)/2

middlePoint = [middlePointX,middlePointY]
print middlePoint

#flipping:
for myLetter in myLetters:
	
	myPaths = myLetter.paths
	
	for myPath in myPaths:  
		for myNodes in myPath.nodes:
			myNodes.x = middlePoint[0]-(myNodes.x-middlePoint[0])
			myNodes.y = middlePoint[1]-(myNodes.y-middlePoint[1])
	index += 1
	
flippedLSB = myLetter.RSB
flippedRSB = myLetter.LSB
myLetter.LSB = flippedLSB
myLetter.RSB = flippedRSB

I tried your corner script and it almost works. There is loop at the bottom of the script that seems relies on a missing variable: listOfSelectedLayers and calls a missing method: unRound.

iterating over all layers of a glyph:

selectedLayer = Font.selectedLayers[0]
for layer in selectedLayer.parent.layers:
    print layer

I tried your corner script and it almost works. There is loop at the bottom of the script that seems relies on a missing variable: listOfSelectedLayers and calls a missing method: unRound.

Thanks,I missed that. To be honest I copied these lines of code from other script and tried to figure out how it works. As a begginer I still have problems with using some methods, functions etc. In this example beginUndo/endUndo. I will figure it out

iterating over all layers of a glyph:

selectedLayer = Font.selectedLayers[0]
for layer in selectedLayer.parent.layers:
print layer

With printing informations about layer works fine. I did something wrong with for-loop. I get error message

Traceback (most recent call last):
File “”, line 12, in
TypeError: ‘NSKVONotifying_GSLayer’ object is not iterable

#MenuTitle: flipper left/right
# -*- coding: utf-8 -*-
__doc__="""flips along axis y"""

selectedLayer = Font.selectedLayers[0]
print selectedLayer
for myLetters in selectedLayer.parent.layers:
	#counting x of middle point
	
	
	allXnodes = []
	for myLetter in myLetters:
		
		myPaths = myLetter.paths
		
		for myPath in myPaths:  
			for myNodes in myPath.nodes:
					allXnodes.append(myNodes.x)	
		
	minXvalue = min(allXnodes)
	
	maxXvalue = max(allXnodes)
	#This is x value of mille point:
	middlePointX = maxXvalue - (maxXvalue - minXvalue)/2
	
	
	myMaster = Glyphs.font.selectedFontMaster
	totalHeight = myMaster.xHeight
	myLetters = Glyphs.font.selectedLayers
	
	#counting y of middle point
	
	allYnodes = []
	for myLetter in myLetters:
		
		myPaths = myLetter.paths
		
		for myPath in myPaths:  
			for myNodes in myPath.nodes:
					allYnodes.append(myNodes.y)	
		
	minYvalue = min(allYnodes)
	
	maxYvalue = max(allYnodes)
	#This is y value of mille point:
	middlePointY = maxYvalue - (maxYvalue - minYvalue)/2
	
	middlePoint = [middlePointX,middlePointY]
	print middlePoint
	
	#flipping:
	for myLetter in myLetters:
		
		myPaths = myLetter.paths
		
		for myPath in myPaths:  
			for myNodes in myPath.nodes:
				myNodes.x = middlePoint[0]-(myNodes.x-middlePoint[0])
				myNodes.y = middlePoint[1]-(myNodes.y-middlePoint[1])
		
	flippedLSB = myLetter.RSB
	flippedRSB = myLetter.LSB
	myLetter.LSB = flippedLSB
	myLetter.RSB = flippedRSB

I hope my posts are not too annoying:
I can not deal with one thing whole day:
My script,which should flip components (and paths) works correctly only with one component.
If there are more than one component, code will mess with components’ positions.
I have been searching the code for few hours, but I haven’t found the problem.
Thanks for help.

test_flipper.py.zip (972 Bytes)

1 Like

Works for me. I like it. :slight_smile: