diff --git a/README.md b/README.md index ea3ac1e0..f489f6e9 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,24 @@ If you enjoy this, make a small donation [here](https://www.paypal.com/cgi-bin/w ---- +![s101](s101/s101.gif) + +101: [code](https://github.com/villares/sketch-a-day/tree/master/s101) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] + +```python + for _ in range(grid_elem * 2): + stroke1, x1, y1, es1 = rnd_choice(ELEMENTS) + stroke(stroke1) + ellipse(x1, y1, es1, es1) + stroke2, x2, y2, es2 = rnd_choice(ELEMENTS) + stroke(stroke2) + # line + ellipse(x2, y2, es2, es2) + line(x1, y1, x2, y2) +``` + +---- + ![s100](s100/s100.gif) 100: [code](https://github.com/villares/sketch-a-day/tree/master/s100) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] diff --git a/s101/gif_exporter.py b/s101/gif_exporter.py new file mode 100644 index 00000000..dbc50ae7 --- /dev/null +++ b/s101/gif_exporter.py @@ -0,0 +1,43 @@ +""" +Alexandre B A Villares http://abav.lugaralgum.com - GPL v3 + +A helper for the Processing gifAnimation library (https://github.com/jordanorelli) +ported to Processing 3 by 01010101 (https://github.com/01010101) +Download the library from https://github.com/01010101/GifAnimation/archive/master.zip +This helper was inspired by an example by Art Simon https://github.com/APCSPrinciples/AnimatedGIF/ + +Put at the start of your sketch: + add_library('gifAnimation') + from gif_exporter import gif_export +and at the end of draw(): + gif_export(GifMaker) +""" + +def gif_export(GifMaker, # gets a reference to the library + filename="exported", # .gif will be added + repeat=0, # 0 makes it an "endless" animation + quality=182, # quality range 0 - 255 + delay=170, # this is quick + frames=0): # 0 will stop on keyPressed or frameCount >= 100000 + global gifExporter + try: + gifExporter + except NameError: + gifExporter = GifMaker(this, filename + ".gif") + gifExporter.setRepeat(repeat) + gifExporter.setQuality(quality) + gifExporter.setDelay(delay) + gif_export._frame = frameCount + print("gif start") + + gifExporter.addFrame() + + if (frames == 0 and keyPressed or frameCount - gif_export._frame >= 100000) \ + or (frames != 0 and frameCount - gif_export._frame >= frames): + gifExporter.finish() + background(255) + print("gif saved") + del(gifExporter) + return False + else: + return True diff --git a/s101/inputs.py b/s101/inputs.py new file mode 100644 index 00000000..6fe0e183 --- /dev/null +++ b/s101/inputs.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from javax.swing import JOptionPane + +""" +This will hpefully switch between Arduino (Firmata) variable input and +nice sliders based on Peter Farell's Sliders htts://twitter.com/hackingmath +https://github.com/hackingmath/python-sliders http://farrellpolymath.com/ +""" +class Input: + + def __init__(self, Arduino, slider_pins): + self.select_source(Arduino) + if self.source > 0: + self.arduino = Arduino(this, Arduino.list()[self.source], 57600) + else: + # start, end, default + A = Slider(0, 1023, 128) + B = Slider(0, 1023, 128) + C = Slider(0, 1023, 128) + D = Slider(0, 1023, 128) + A.position(40, height - 70) + B.position(40, height - 30) + C.position(width - 140, height - 70) + D.position(width - 140, height - 30) + a, b, c, d = slider_pins + self.sliders = {a: A, b: B, c: C, d: D} + + def analog(self, pin): + if self.source: + return self.arduino.analogRead(pin) + else: + return self.sliders[pin].val + + def update(self): + if not self.source: + for pin, slider in self.sliders.iteritems(): + slider.update() + + def keyPressed(self): + if key == 'a': + self.sliders[1].down = True + if key == 'd': + self.sliders[1].up = True + if key == 's': + self.sliders[2].down = True + if key == 'w': + self.sliders[2].up = True + if keyCode == LEFT: + self.sliders[3].down = True + if keyCode == RIGHT: + self.sliders[3].up = True + if keyCode == DOWN: + self.sliders[4].down = True + if keyCode == UP: + self.sliders[4].up = True + + def keyReleased(self): + if key == 'a': + self.sliders[1].down = False + if key == 'd': + self.sliders[1].up = False + if key == 's': + self.sliders[2].down = False + if key == 'w': + self.sliders[2].up = False + if keyCode == LEFT: + self.sliders[3].down = False + if keyCode == RIGHT: + self.sliders[3].up = False + if keyCode == DOWN: + self.sliders[4].down = False + if keyCode == UP: + self.sliders[4].up = False + + def digital(self, pin): + space_pressed = keyPressed and key == ' ' + if self.source: + if pin == 13: + return self.arduino.digitalRead(13) or space_pressed + else: + return arduino.digitalRead(pin) + else: + return space_pressed + + def select_source(self, Arduino): + # Input.Arduino = Arduino # to make available on this module + port_list = [str(num) + ": " + port for num, port + in enumerate(Arduino.list())] + if not port_list: + port_list.append(None) + self.source = option_pane("O seu Arduino está conectado?", + "Escolha a porta ou pressione Cancel\npara usar 'sliders':", + port_list, + -1) # index for default option + self.help() + + def help(self): + if self.source: + message = """ Teclas: + 'h' para esta ajuda + 'p' para salvar uma imagem + 'g' para salvar um GIF + Tombe a lousa para lousa para limpar o desenho!""" + else: + message = """ Teclas: + 'h' para esta ajuda + 'p' para salvar uma imagem + 'g' para salvar um GIF + 'a' (-) ou 'd' (+) para o slider 1 + 's' (-) ou 'w' (+) para o slider 2 + ←(-) ou → (+) para o slider 3 + ↓ (-) ou ↑ (+) para o slider 4 + [barra de espaço] para limpar o desenho""" + ok = JOptionPane.showMessageDialog(None, message) + + +def option_pane(title, message, options, default=None, index_only=True): + + if default == None: + default = options[0] + elif index_only: + default = options[default] + + selection = JOptionPane.showInputDialog( + frame, + message, + title, + JOptionPane.INFORMATION_MESSAGE, + None, # for Java null + options, + default) # must be in options, otherwise 1st is shown + if selection: + if index_only: + return options.index(selection) + else: + return selection + +class Slider: + + SLIDERS = [] + + def __init__(self, low, high, default): + '''slider has range from low to high + and is set to default''' + self.low = low + self.high = high + self.val = default + self.clicked = False + self.up, self.down = False, False + Slider.SLIDERS.append(self) + + def position(self, x, y): + '''slider's position on screen''' + self.x = x + self.y = y + # the position of the rect you slide: + self.rectx = self.x + map(self.val, self.low, self.high, 0, 120) + self.recty = self.y - 10 + + def update(self): + '''updates the slider''' + pushStyle() + rectMode(CENTER) + # black translucid rect behind slider + fill(0, 100) + noStroke() + rect(self.x + 60, self.y, 130, 20) + # gray line behind slider + strokeWeight(4) + stroke(200) + line(self.x, self.y, self.x + 120, self.y) + # press mouse to move slider + if (self.x < mouseX < self.x + 120 and + self.y < mouseY < self.y + 20): + fill(250) + textSize(10) + text(str(int(self.val)), self.rectx, self.recty + 35) + if mousePressed: + self.rectx = mouseX + # key usage + if self.up: + self.rectx += 1 + if self.down: + self.rectx -= 1 + # constrain rectangle + self.rectx = constrain(self.rectx, self.x, self.x + 120) + # draw rectangle + strokeWeight(1) + fill(255) + rect(self.rectx, self.recty + 10, 10, 20) + self.val = map(self.rectx, self.x, self.x + 120, self.low, self.high) + popStyle() diff --git a/s101/s100.gif b/s101/s100.gif new file mode 100644 index 00000000..6a3d3d3e Binary files /dev/null and b/s101/s100.gif differ diff --git a/s101/s101.gif b/s101/s101.gif new file mode 100644 index 00000000..d2073b4f Binary files /dev/null and b/s101/s101.gif differ diff --git a/s101/s101.pyde b/s101/s101.pyde new file mode 100644 index 00000000..955e6429 --- /dev/null +++ b/s101/s101.pyde @@ -0,0 +1,89 @@ +# Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day +SKETCH_NAME = "s101" # 180411 + +add_library('serial') # import processing.serial.*; +add_library('arduino') # import cc.arduino.*; +add_library('gifAnimation') + +from gif_exporter import * +from inputs import * + +def setup(): + global input, GIF_EXPORT, ELEMENTS + size(600, 600) + noFill() # sem contorno + frameRate(30) + strokeWeight(3) + ELEMENTS = [] + GIF_EXPORT = False + # Ask user for Arduino port, uses slider if none is selected` + input = Input(Arduino, slider_pins=[1, 2, 3, 4]) + +def draw(): + background(127) # fundo cinza claro + + grid_elem = int(input.analog(1) / 16) # 0 a 63 linhas e colunas na grade + elem_size = int(input.analog(2) / 16) # 0 a 63 tamanho base dos quadrados + rand_size = int(input.analog(3) / 16) # escala a randomização do tamanho + rand_posi = int(input.analog(4) / 16) # escala a randomização da posição + # trava a random entre os ciclos de draw + # mas varia com o número de colunas na grade + randomSeed(int(input.analog(1)) / 4) + # espaçamento entre os elementos + spac_size = int(width / (grid_elem + 1)) + for _ in range(3): + for x in range(spac_size / 2, width, spac_size): + for y in range(spac_size / 2, width, spac_size): + final_size = elem_size + rand_size * random(-1, 1) + offsetX = rand_posi * random(-1, 1) + offsetY = rand_posi * random(-1, 1) + C = map(final_size, 0, 63, 0, 255) + ELEMENTS.append((C, + x + offsetX, + y + offsetY, + final_size + )) + + for _ in range(grid_elem * 2): + stroke1 x1, y1, es = rnd_choice(ELEMENTS) + stroke(stroke1) + ellipse(x1, y1, es1, es1) + stroke2, x2, y2, es2 = rnd_choice(ELEMENTS) + stroke(stroke2) + ellipse(x2, y2, es2, es2) + line(x1, y1, x2, y2) + + # empty list + ELEMENTS[:] = [] + + + + # uncomment next lines to export GIF + global GIF_EXPORT + if not frameCount % 20 and GIF_EXPORT: + GIF_EXPORT = gif_export(GifMaker, + frames=1000, + delay=300, + filename=SKETCH_NAME) + + # Updates reading or draws sliders and checks mouse dragging / keystrokes + input.update() + + +def keyPressed(): + global GIF_EXPORT + if key == 'p': # save PNG + saveFrame("####.png") + if key == 'g': # save GIF + GIF_EXPORT = True + if key == 'h': + input.help() + + input.keyPressed() + +def keyReleased(): + input.keyReleased() + +def rnd_choice(collection): + i = int(random(len(collection))) + return collection[i]