Thanks Frederik you've helped me a lot!!!
Posts made by eduairet
-
RE: Script to Standalone app
@eduairet I tried this and now opens the script and it's not giving me errors but it still doesn't run entirely:
openWindows = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements, Quartz.kCGNullWindowID ) openWindows = [window.get('kCGWindowName', u'Unknown').encode('ascii','ignore') for window in openWindows if window['kCGWindowOwnerName'] == 'DrawBot'] if b'main.py' not in openWindows: os.system(f'open -a DrawBot {__file__}')
-
RE: Script to Standalone app
Debugger shows the problem now:
Traceback (most recent call last): File "main.py", line 45, in <module> File "drawBot/drawBotDrawingTools.pyc", line 2548, in Variable drawBot.misc.DrawBotError: There is no document open
It works if I run
main.py
does it need to open a window first and then run Variable? -
RE: Script to Standalone app
@frederik thanks!!! I just got curious about it. I'm having a problem with the package, it doesn't open the script when I open it in DrawBot, this is the tree I have
myPackage.drawbot βββ info.plist βββ lib βββ squareAdjustments.py βββ logoAdjustments.py βββ fontAdjustments.py βββ userText.py βββ main.py βββ resources βΒ Β βββ fonts βΒ Β βββ VF.ttf βΒ Β βββ Logo.otf βββ save.py
When I open main by itself it runs
-
RE: Script to Standalone app
Is there a way to execute the Run command using shell or applescript?
-
RE: Script to Standalone app
@frederik sweet, Iβll give the package a try, I thought about using the app because it needs to be an executable and avoid the run part of the workflow.
-
Script to Standalone app
Hey there!
I'm attempting to make a standalone app with a drawbot script using
py2app
anddrawBot
as a module. I'm having a lot of trouble with the Variable menu, the error I'm having so far israise DrawBotError("There is no document open")
when the script gets toVariable(menuElements, globals())
I'm speculating about how to solve it, Do I need to assign a document to the class or something like that? -
RE: Chess board in one loop
@monomonnik Wow! This is beautiful, thanks for taking your time making an approach, and also for sharing it. It makes sense how you solve it and gives me more ideas to make more challenges like this!
-
Chess board in one loop
Hi everyone, I'm putting some effort making basic exercises more challenging, right now I'm struggling with a chess board, I usually solve this with two loops and conditionals, but my challenge is to do it in one loop and with no conditionals, here is what I've done so far:
side = 800 newPage(side, side) square = side//8 with savedState(): fill(1), rect(0, 0, side, side) y, advance = 0, 0 while y < side: rect(square * (advance%2), y, square, square) rect(square * (advance%2) + square*2, y, square, square) rect(square * (advance%2) + square*4, y, square, square) rect(square * (advance%2) + square*6, y, square, square) y += square advance += 1
Do you have any smarter idea to solve this coding challenge?
Thanks! -
RE: Gradient rings from Python for Designers tutorial
@frederik thank you very much! I'll implement this way
-
Gradient rings from Python for Designers tutorial
Hello everyone!!!
I'm attempting to solve the exΒerΒcise 14.4 of @roberto-arista 's pythonfordesigners.com/chapters/workbook/ I'm having a problem with my approach, I decided to use circles instead of lines and I couldn't find a way to make a smooth gradient without having a weird hole in the middle of the right top and right bottom blending, here's a photo of it:
# 14.4 def donuts(circSize=10, cnvSize=200): def intrp(factor, val1, val2): return val1 + (val2 - val1) * factor def intrRgb(factor, col1, col2): r = intrp(factor, col1[0], col2[0]) g = intrp(factor, col1[1], col2[1]) b = intrp(factor, col1[2], col2[2]) return r, g, b def circCoords(radius, circSize=10): cirCoords = [] an = 0 anMulti = 0 for i in range(cnvSize+1): for j in range(cnvSize): cirCoords.append([ radius * sin(pi * 2 * an / 360) - halfCirc, radius * cos(pi * 2 * an / 360) - halfCirc ]) an += 360/(cnvSize*cnvSize) return sorted(cirCoords) def mapColors(c1, c2, c3, c4): colors = [] for x in range(cnvSize): xFactor = x/cnvSize for y in range(cnvSize): yFactor = y / cnvSize lftClr = intrRgb(yFactor, c4, c1) rgtClr = intrRgb(yFactor, c3, c2) colors.append(intrRgb(xFactor, lftClr, rgtClr)) return colors halfCirc = circSize/2 colors = {'lftTop': (1, 0, 0.8), 'rgtTop': (1, 1, 0.3), 'rgtBtm': (1, .8, 0), 'lftBtm': (0, 0.5, 1)} colors = mapColors(colors['lftTop'], colors['rgtTop'], colors['rgtBtm'], colors['lftBtm']) circles = [circCoords(cnvSize*0.4, circSize), circCoords(cnvSize*0.25, circSize), circCoords(cnvSize*0.1, circSize)] newPage(cnvSize, cnvSize) inc = 0 for x in range(cnvSize): for y in range(cnvSize): fill(*colors[inc]) if x == 0 and y == 0 or x == 0 and y == cnvSize-1 or x == cnvSize-1 and y == 0 or x == cnvSize-1 and y == cnvSize-1: oval(x - halfCirc, y - halfCirc, circSize, circSize) if y == int(circles[0][inc][1]) + cnvSize/2 - 1 or y == int(circles[0][inc][1]) + cnvSize - 100: for circ in circles: with savedState(): translate(cnvSize/2, cnvSize/2) oval(circ[inc][0], circ[inc][1], circSize, circSize) inc += 1 # Call the function donuts()
Hope you can help me, feedback on my approach would be great too, thank you!!!!!!!
-
RE: how to code a gif that gradually transform one picture into another
Hi, hope this helps:
# Get your gif routes gifsFolder = '.' # Your gifs directory gifs = ['gif1.gif', 'gif2.gif'] # These are the files I'll use gifPaths = [f'{gifsFolder}/{gif}' for gif in gifs] # Create the paths for your with string formattingx # Create a function to interpolate between gifs def scaleFactor(path, pageNumber, canvasSize): # Get a scale factor to match the canvas size you want gifw, gifh = imageSize(path, pageNumber=pageNumber) factorMeasure = gifw if gifw > gifh: factorMeasure = gifh return canvasSize / factorMeasure def gifTransition(path1, path2): # Canvas and images dimensions w, h = 200, 200 # Canvas size # Define your frames introFrames = numberOfPages(path1) endingFrames = numberOfPages(path2) crossfadeFrames = 12 # Change this value for a longer transition totalFrames = int( (introFrames - crossfadeFrames/2)+(endingFrames - crossfadeFrames/2) ) # Get the total frames by merging the crossfade in the middle # Make a loop for the animation gif1Frames, gif2Frames = 0, 0 gif1alpha, gif2alpha = 1, 0 for frame in range(1, totalFrames+1): newPage(w, h) fill(1) rect(0, 0, w, h) with savedState(): scale(scaleFactor(path1, gif1Frames, w)) image(path1, (0, 0), pageNumber=gif1Frames, alpha=gif1alpha) if gif1Frames < introFrames: gif1Frames += 1 if frame > introFrames - crossfadeFrames/2: # Run the second gif with savedState(): scale(scaleFactor(path2, gif2Frames, w)) image(path2, (0, 0), pageNumber=gif2Frames, alpha=gif2alpha) gif2Frames += 1 if gif1alpha >= 0 or gif2alpha <= 1: # Crossfade transparency gif1alpha -= 1 / crossfadeFrames gif2alpha += 1 / crossfadeFrames gifTransition(gifPaths[0], gifPaths[1]) # Call the function saveImage('~/Desktop/gifCrossfade.gif') # Save your gif
-
RE: Tutorial Request: Delay Animation
I found this very interesting so I tried to do it without a lot of success, I ended with something like this:
w, h = 1000, 1000 divs = 10 colSize, rowSize = w//divs, h//divs fps = 12 seconds = 1 duration = 1 / fps totalFrames = seconds * fps def circles(step): for x in range(0, w, colSize): for y in range(0, h, rowSize): d = rowSize * sin(y/(divs/2)+step) if d > 0: fill(1) else: fill(1, 0, 0) oval(x + colSize/2 - d/2, y + rowSize/2 - d/2 , d, d) for frame in range(totalFrames): newPage(w, h) frameDuration(duration) fill(0) rect(0, 0, w, h) circles(frame) saveImage("~/Desktop/circleTest.gif")
I'm not understanding how the time works in the reference to achieve the smooth variation
-
Vertical Align
I'm looking for a property to work with textBox() to align the text to the vertical center. What I'm imagining is something like this:
textBox( 'DrawBot is great', ( width()*0.2, height()*0.2, width()*0.6, height()*0.6 ), align = 'center', verticalAlign = 'center' )
This way you can come up with a random playing with that verticalAlign or something like that
-
RE: Loop image generation breaks at index 16
@frederik OMG it works now!!! thank you very much!!!! Happy holidays!!!
-
RE: Loop image generation breaks at index 16
Here a handy script to generate files to test, if you use it this way you should change the following line:
if len(row['\ufeffNAME']) > 0: data.append(row['\ufeffNAME'])
to
if len(row['NAME']) > 0: data.append(row['NAME'])
import os import csv def fullNameGenerator(): name = '' lastName = '' for letter in range(randint(4,10)): name += choice(letters) for letter in range(randint(4,10)): lastName += choice(letters) fullName = name.title() + ' ' + lastName.title() return fullName letters = 'abcdefghijklmnopqrstuvwxyz' myMessage ='I wish you the best holidays ever! With All my love for you:' myPath = './' myDir = 'dataFiles' myDirPath = myPath + myDir if myDir not in os.listdir(myPath): os.mkdir(myPath + myDir) with open(myDirPath + '/xmasMessage.txt', 'w') as xmasMsg: xmasMsg.write(myMessage) with open(myDirPath + '/xmasList.csv', 'w', newline='') as xmasList: csv_writter = csv.writer(xmasList) csv_writter.writerow(['NAME']) names = [] for i in range(40): names.append([fullNameGenerator()]) for row in names: csv_writter.writerow(row)
And the snowflake pdf
https://drive.google.com/file/d/1EZxopDsOjd-K7ur-QQm-Xc_0zj7dGPkv/view?usp=sharingThanks again!!
-
Loop image generation breaks at index 16
Hi, I'm making custom Christmas gif postcards, everything's working until the loop reaches the 16th value of my list, I tried making them individually and it works, but when I try a for loop it gets stuck like in an infinite loop but I don't know why. Does anyone know what's happening?
import csv import unicodedata import os def strip_accents(text): try: text = unicode(text, 'utf-8') except NameError: # unicode is a default on python 3 pass text = unicodedata.normalize('NFD', text)\ .encode('ascii', 'ignore')\ .decode("utf-8") return str(text) # Typeface canelaUnordered = [] for font in installedFonts(): if 'Canela' in font: canelaUnordered.append(font) canelaIndexes = [2, 3, 0, 1, 8, 9, 6, 7, 4, 5, 14, 15, 12, 13, 10, 11] canela = [] for i in range(len(canelaUnordered)): canela.append(canelaUnordered[canelaIndexes[i]]) # Data for custom images data = [] with open('./xmasList.csv', newline='', encoding='UTF-8') as data_csv: data_reader = csv.DictReader(data_csv, delimiter=',', quotechar='|') for row in data_reader: if len(row['\ufeffNAME']) > 0: data.append(row['\ufeffNAME']) # Main copywrite cw = open('./xmasMessage.txt', 'r', encoding='UTF-8') cw = cw.read() # Design class class Postcard(): def __init__(self, x=1600, y=1600, m=160): self.x = x self.y = y self.m = m self.tree = BezierPath() self.tree.moveTo((self.m, self.y*0.18)) self.tree.lineTo((self.x/2, self.y *0.90)) self.tree.lineTo((self.x - (self.m), self.y*0.18)) self.tree.closePath() def c(self, val): if type(isinstance(val, (int, float))): if val <= 255: return val / 255 else: raise Exception("Sorry, just numbers below 255") def hexToRGB(self, val): val = val.lstrip('#') lv = len(val) color = [int(val[i:i + lv // 3], 16) for i in range(0, lv, lv // 3)] r, g, b = color[0], color[1], color[2] return self.c(r), self.c(g), self.c(b) def copy(self, cw = cw): self.cw = cw words = self.cw.split() txtFillone = self.hexToRGB('#FFFFFF') txt = FormattedString( 'β’\n', font = canela[1], fontSize=160, lineHeight=200, fill = (txtFillone[0], txtFillone[1], txtFillone[2]), align = 'center' ) txt.append('2020\n'.upper(), font=canela[1], fontSize=158, lineHeight=159) txt.append('Merry '.upper(), font = canela[4], fontSize=94, lineHeight=100) txt.append('Xmas'.upper() + '\nβ’\n', font = canela[2]) boldWords = ['holidays'] breakWords = ['ever!'] for word in words: txt.append('', fontSize=48, lineHeight=52, paragraphBottomSpacing=52) if word in boldWords: txt.append(word + ' ', font = canela[13]) elif word in breakWords: txt.append(word + '\n', font = canela[13]) else: txt.append(word + ' ', font = canela[11]) logo = FormattedString( 'Sincerely eat\n', align='center', font = canela[10], fontSize=80, lineHeight=180, fill=(1) ) textBox(txt, self.tree) text(logo, (self.x/2, self.m)) def receiver(self, tx, limit = 100): rFnt = canela[2] textSize = FormattedString(tx, font = rFnt, fontSize=1, lineHeight=1, align='center') rSz = 1180 / textSize.size()[0] if rSz > limit: rSz = limit receiver = FormattedString(tx,font=rFnt, fontSize=rSz, lineHeight=rSz, align='center', fill=(1)) text(receiver, (self.x/2, self.y*0.20)) stroke(2) strokeWidth(6) line((self.x*0.17, self.y*0.28), (self.x*0.83, self.y*0.28)) def snow(self, copos=30, path='./snowFlake.pdf'): w, h = imageSize(path) copo = ImageObject(path) for i in range(copos): scaleFactor = randint(1, 5) * 0.1 with savedState(): translate(randint(0, self.x), randint(self.y*0.12, self.y)) scale(scaleFactor) image(copo, (-w/2, -h/2)) def canvas(self, bgColor='#FF5900'): newPage(self.x, self.y) if type(bgColor) == list: self.bgColor = self.c(bgColor[0]), self.c(bgColor[1]), self.c(bgColor[2]) elif type(bgColor) == str: if len(bgColor) == 7 or len(bgColor) == 4 or len(bgColor) == 6 or len(bgColor) == 3: self.bgColor = self.hexToRGB(bgColor) else: raise Exception("Sorry, incorrect HexValue") else: raise Exception("Sorry, use one of the following formats: [r, g, b] or Hex value") fill(self.bgColor[0], self.bgColor[1], self.bgColor[2]) rect(0, 0, self.x, self.y) def drawTree(self, deg): fill(0.1, 0.4, 0.3) stroke(0.1, 0.4, 0.3) strokeWidth(100) with savedState(): rotate(deg, center=(self.x/2, self.y/2)) drawPath(self.tree) def save(self, tx, user='eat', message='merryXmas2020'): fileName = strip_accents(tx).lower().strip().replace(' ', '_') saveDir = '2020_xmasCards' saveLoc = '/Users/{}/Desktop/'.format(user) if saveDir not in os.listdir(path=saveLoc): os.mkdir(saveLoc + saveDir) saveImage(saveLoc + saveDir + '/' + message + '_{}.gif'.format(fileName), imageResolution = 72) print(message + '_{}.gif'.format(fileName) + ' Done') newDrawing() def postcardGenerator(data, save=True, frames = 2): deg = 2 rot = -2 for i in range(frames): card = Postcard() card.canvas() card.drawTree(deg) card.snow() card.copy() card.receiver(data) if i == int(frames/2): rot *= -1 deg += rot if save: card.save(data) # Ceate postcards for field in data: postcardGenerator(field) # testNum = 0 # postcardGenerator(data[testNum], False)
If you make the whole list with the testNum it works which makes me think that the problem is not in the external files I'm using.
Thank you for your help!!
-
RE: QRCodeGenerator(size, message)
@gferreira WOW!!!! you saved my ass again, you're amazing, thanks a lot!!!
-
QRCodeGenerator(size, message)
Hi DrawBot fellas!!
I'm struggling with the QRCodeGenerator() ImageObject() property, I got two errors, the first one is TypeError: Expecting byte-buffer, got str when I try to pass a URL, and when I try to encode the URL TypeError: cannot unpack non-iterable float object
Is it possible that you can help me to figure out what's happening?
Here's the way I'd love to use it:
path = 'https://www.mypath.com' newPage(1000, 1000) qr = ImageObject() path = path.encode('utf-8') qr.QRCodeGenerator(100, path) image(qr, (0, 0, width(), height()))
And here's the way I made it with the qrcode module by making a png first and then using it inside my drawbot image
import qrcode path = 'https//:www.mypath.com' qr = qrcode.QRCode( version = 1, error_correction = qrcode.constants.ERROR_CORRECT_L, box_size = 40, border = 0, ) qr.add_data(path) qr.make(fit=True) img = qr.make_image(fill_color='black', back_color='white') qrpath = 'myQr.png' img.save(qrpath) image(qrpath, (0, 0))
Thank you!!!