def on_mouse_press(self, mouse): x0, y0 = self.absolute_position() # Can be nested in other layers. step = 1.0 / max(self.steps, 1) # Calculate relative value from the slider handle position. # The inner width is a bit smaller to accomodate for the slider handle. # Clamp the relative value to the nearest step. self._t = (mouse.x - x0 - self.height * 0.5) / float(self.width - self.height) self._t = self._t - self._t % step + step self._t = clamp(self._t, 0.0, 1.0) self.on_action()
def on_mouse_press(self, mouse): x0, y0 = self.absolute_position() # Can be nested in other layers. step = 1.0 / max(self.steps, 1) # Calculate relative value from the slider handle position. # The inner width is a bit smaller to accomodate for the slider handle. # Clamp the relative value to the nearest step. self._t = (mouse.x-x0-self.height*0.5) / float(self.width-self.height) self._t = self._t - self._t % step + step self._t = clamp(self._t, 0.0, 1.0) self.on_action()
def _set_value(self, value): self._t = clamp(float(value - self.min) / (self.max - self.min or -1), 0.0, 1.0)
def draw(canvas): global headset global dimmer global images global samples global particles global attractor global ZOOM, ATTRACT, SPAWN, DIM, delay global MUTE glEnable(GL_DITHER) background(0) #image(abspath("g","bg.png"), 0, 0, width=canvas.width, height=canvas.height) image(abspath("g","bg-light.png"), 0, 0, width=canvas.width, height=canvas.height, alpha=0.9) if canvas.key.code == SPACE: MUTE = not MUTE # Poll the headset. # Is alpha above average? => attraction. # Is valence above average? => spawn feelies. headset.update(buffer=1024) ATTRACT = False ATTRACT = delay > 0 ATTRACT = ATTRACT or SHIFT in canvas.key.modifiers if canvas.key.code == SHIFT: ATTRACT = True if len(headset.alpha[0]) > 0 and headset.alpha[0][-1][0] > headset.alpha[0][-1][1] * 1.0: ATTRACT = True delay = 10 # Delay before repulsing to counter small alpha fluctuation. elif delay > 0: delay -= 1 SPAWN = False SPAWN = CTRL in canvas.key.modifiers if canvas.key.code == CTRL: SPAWN = True if len(headset.valence) > 0 and headset.valence[-1][0] > headset.valence[-1][1]: SPAWN = True # In mute mode, ignore triggering alpha and valence. if MUTE: ATTRACT = SPAWN = False delay = 0 # Dimmer sends a value over UDP that drops to 0 when relaxed. # It can be used to dim ambient lighting using a domotica module. m = 0.0025 if ATTRACT: DIM = clamp(DIM-m, 0.0, 1.0) else: DIM = clamp(DIM+m, 0.0, 1.0) if DIM < 0.8 and dimmer is not None: dimmer.send("%.2f" % (DIM * 100)) # Valence controls the balance between high and low ambient. v = headset.valence.slope # -1.0 => +1.0 v = 0.0 dx = 1.0 - v dy = 1.0 + v # Mouse changes the volume of low and high ambient sound. #dx = canvas.mouse.relative_x #dy = canvas.mouse.relative_y samples["ambient_lo"].play(volume=0.7 * dx) samples["ambient_hi"].play(volume=0.7 * dy) if canvas.key.code == ALT: text("%.2f FPS" % canvas.profiler.framerate, canvas.width-80, 15, align=RIGHT, fill=[1,1,1,0.75]) if canvas.frame / 20 % 2 == 0: fill(1,1,1, 0.75) fontsize(9) if len(headset.alpha[0]) > 0: ellipse(canvas.width-18, 19.5, 7, 7, fill=[1,1,1,1]) if ATTRACT or SPAWN: ellipse(15, 19.5, 7, 7, fill=[1,0,0,1]) if ATTRACT and SPAWN: text(" RELAXATION + AROUSAL", 20, 15) elif ATTRACT: text(" RELAXATION", 20, 15) elif SPAWN: text(" AROUSAL", 20, 15) elif MUTE: text(" READY", 20, 15) # Zoom out as the attractor grows larger. # Integrate the zoom scale to make the transition smoother. d = (1.25 - len(attractor.particles) * 0.05) if ZOOM > -0.15 and ZOOM > d: ZOOM -= 0.0025 if ZOOM < +1.25 and ZOOM < d: ZOOM += 0.0025 dx = 0.5 * ZOOM * canvas.width dy = 0.5 * ZOOM * canvas.height translate(-dx, -dy) scale(1.0 + ZOOM) for p in list(particles): d = distance(p.x, p.y, attractor.x, attractor.y) t = d / canvas.width * 2 p.update() # When valence is low, unattached feelie particles fade away. if SPAWN is False: if p.parent is None and p.type == FEELIE: p.alpha -= 0.04 p.alpha = max(p.alpha, 0) if p.alpha == 0: # Remove hidden feelies, so we have a chance to see new ones. particles.remove(p) # Check if a particle falls within the attraction radius: # If so, attract it when alpha is above average. if ATTRACT is True: if p.parent is None and p.frames >= 0 and p.alpha >= 0.25: if d < min(210, p.radius + attractor.radius * attractor.gravity): attractor.append(p) samples["attract"].play().volume = 0.75 p.draw(blur=t, alpha=(1-t)) # Repulse when alpha drops below average. # Press mouse to repulse attracted particles. if ATTRACT is False: if random() > 0.5: if len(attractor.particles) > 0: attractor.remove(attractor.particles[0]) samples["repulse"].play() # When valence is high, feelie particles appear. if SPAWN is True: if random() > 0.5: if len(particles) < 80: p = Particle(x = choice((-30, canvas.width+30)), y = -30, image = choice([images["flower%i.png"%i] for i in range(2,6+1)], bias=0.25), radius = 15 + random(20), bounds = (-65, -65, canvas.width+65, canvas.height+65), speed = 3.5, type = FEELIE) if p.image._src[0].endswith("flower3.png"): p.radius = 20 + random(20) if p.image._src[0].endswith("flower4.png"): p.radius = 15 + random(10) if p.image._src[0].endswith("flower5.png"): p.radius = 15 if p.image._src[0].endswith("flower6.png"): p.radius = 10 + random(5) particles.append(p) attractor.update() attractor.draw_halo() attractor.draw()
def _set_value(self, value): self._t = clamp(float(value-self.min) / (self.max-self.min or -1), 0.0, 1.0)
def draw(canvas): global headset global dimmer global images global samples global particles global attractor global ZOOM, ATTRACT, SPAWN, DIM, delay global MUTE glEnable(GL_DITHER) background(0) #image(abspath("g","bg.png"), 0, 0, width=canvas.width, height=canvas.height) image(abspath("g", "bg-light.png"), 0, 0, width=canvas.width, height=canvas.height, alpha=0.9) if canvas.key.code == SPACE: MUTE = not MUTE # Poll the headset. # Is alpha above average? => attraction. # Is valence above average? => spawn feelies. headset.update(buffer=1024) ATTRACT = False ATTRACT = delay > 0 ATTRACT = ATTRACT or SHIFT in canvas.key.modifiers if canvas.key.code == SHIFT: ATTRACT = True if len(headset.alpha[0] ) > 0 and headset.alpha[0][-1][0] > headset.alpha[0][-1][1] * 1.0: ATTRACT = True delay = 10 # Delay before repulsing to counter small alpha fluctuation. elif delay > 0: delay -= 1 SPAWN = False SPAWN = CTRL in canvas.key.modifiers if canvas.key.code == CTRL: SPAWN = True if len(headset.valence ) > 0 and headset.valence[-1][0] > headset.valence[-1][1]: SPAWN = True # In mute mode, ignore triggering alpha and valence. if MUTE: ATTRACT = SPAWN = False delay = 0 # Dimmer sends a value over UDP that drops to 0 when relaxed. # It can be used to dim ambient lighting using a domotica module. m = 0.0025 if ATTRACT: DIM = clamp(DIM - m, 0.0, 1.0) else: DIM = clamp(DIM + m, 0.0, 1.0) if DIM < 0.8 and dimmer is not None: dimmer.send("%.2f" % (DIM * 100)) # Valence controls the balance between high and low ambient. v = headset.valence.slope # -1.0 => +1.0 v = 0.0 dx = 1.0 - v dy = 1.0 + v # Mouse changes the volume of low and high ambient sound. #dx = canvas.mouse.relative_x #dy = canvas.mouse.relative_y samples["ambient_lo"].play(volume=0.7 * dx) samples["ambient_hi"].play(volume=0.7 * dy) if canvas.key.code == ALT: text("%.2f FPS" % canvas.profiler.framerate, canvas.width - 80, 15, align=RIGHT, fill=[1, 1, 1, 0.75]) if canvas.frame / 20 % 2 == 0: fill(1, 1, 1, 0.75) fontsize(9) if len(headset.alpha[0]) > 0: ellipse(canvas.width - 18, 19.5, 7, 7, fill=[1, 1, 1, 1]) if ATTRACT or SPAWN: ellipse(15, 19.5, 7, 7, fill=[1, 0, 0, 1]) if ATTRACT and SPAWN: text(" RELAXATION + AROUSAL", 20, 15) elif ATTRACT: text(" RELAXATION", 20, 15) elif SPAWN: text(" AROUSAL", 20, 15) elif MUTE: text(" READY", 20, 15) # Zoom out as the attractor grows larger. # Integrate the zoom scale to make the transition smoother. d = (1.25 - len(attractor.particles) * 0.05) if ZOOM > -0.15 and ZOOM > d: ZOOM -= 0.0025 if ZOOM < +1.25 and ZOOM < d: ZOOM += 0.0025 dx = 0.5 * ZOOM * canvas.width dy = 0.5 * ZOOM * canvas.height translate(-dx, -dy) scale(1.0 + ZOOM) for p in list(particles): d = distance(p.x, p.y, attractor.x, attractor.y) t = d / canvas.width * 2 p.update() # When valence is low, unattached feelie particles fade away. if SPAWN is False: if p.parent is None and p.type == FEELIE: p.alpha -= 0.04 p.alpha = max(p.alpha, 0) if p.alpha == 0: # Remove hidden feelies, so we have a chance to see new ones. particles.remove(p) # Check if a particle falls within the attraction radius: # If so, attract it when alpha is above average. if ATTRACT is True: if p.parent is None and p.frames >= 0 and p.alpha >= 0.25: if d < min(210, p.radius + attractor.radius * attractor.gravity): attractor.append(p) samples["attract"].play().volume = 0.75 p.draw(blur=t, alpha=(1 - t)) # Repulse when alpha drops below average. # Press mouse to repulse attracted particles. if ATTRACT is False: if random() > 0.5: if len(attractor.particles) > 0: attractor.remove(attractor.particles[0]) samples["repulse"].play() # When valence is high, feelie particles appear. if SPAWN is True: if random() > 0.5: if len(particles) < 80: p = Particle( x=choice((-30, canvas.width + 30)), y=-30, image=choice( [images["flower%i.png" % i] for i in range(2, 6 + 1)], bias=0.25), radius=15 + random(20), bounds=(-65, -65, canvas.width + 65, canvas.height + 65), speed=3.5, type=FEELIE) if p.image._src[0].endswith("flower3.png"): p.radius = 20 + random(20) if p.image._src[0].endswith("flower4.png"): p.radius = 15 + random(10) if p.image._src[0].endswith("flower5.png"): p.radius = 15 if p.image._src[0].endswith("flower6.png"): p.radius = 10 + random(5) particles.append(p) attractor.update() attractor.draw_halo() attractor.draw()