def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._growth_fader = ColorFade('hsv', [(0., 0., 0.), self._alive_color], tick_rate=self._mixer.get_tick_rate()) self._tail_fader = ColorFade('hsv', [self._alive_color, self._tail_color, (0., 0., 0.)], tick_rate=self._mixer.get_tick_rate())
def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() self._explode_color = self.parameter('explode-color').get() self._growth_fader = ColorFade([(0., 0., 0.), self._alive_color], self._fader_steps) self._tail_fader = ColorFade([self._alive_color, self._tail_color, (0., 0., 0.)], self._fader_steps) self._explode_fader = ColorFade([self._explode_color, (0., 0., 0.)], self._fader_steps)
def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._black_color = self.parameter('black-color').get() fade_colors = [ self._black_color, self._alive_color, self._dead_color, self._black_color ] self._fader = ColorFade(fade_colors, self._fader_steps)
def _setup_colors(self): self._up_target_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('on-color').get())) self._down_target_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('off-color').get())) self._fader = ColorFade('hsv', [ self.parameter('off-color').get(), self.parameter('on-color').get() ])
def _setup_colors(self): self._alive_color_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('alive-color').get())) self._dead_color_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('dead-color').get())) fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._fader = ColorFade('hsv', fade_colors, tick_rate=self._mixer.get_tick_rate())
def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._growth_fader = ColorFade('hsv', [(0., 0., 0.), self._alive_color], tick_rate=self._mixer.get_tick_rate()) self._tail_fader = ColorFade( 'hsv', [self._alive_color, self._tail_color, (0., 0., 0.)], tick_rate=self._mixer.get_tick_rate())
def __init__(self, mixer): super(Audio, self).__init__() self.mixer = mixer self.fft = [[0]] self.smoothed = [] self.average = [[0]] self.peak = [[0]] self.peakFrequency = [[0]] self.gain = 1.0 self.maxGain = 5.0 self.fader = ColorFade([(0,0,1), (0,1,1)], self._fader_steps) self.pitch = 0.0 self.pitch_confidence = 0.0 self.smoothEnergy = 0.0 self._simulate = False self._auto_enable_simulate = False self._sim_timer = QtCore.QTimer(self) self._sim_timer.setInterval(50) self._time_since_last_data = 0 self._sim_beat = 0 self._sim_counter = 0 self._sim_energy = 0.0 self._sim_fft = [] self._sim_timer.timeout.connect(self.on_sim_timer) self._sim_timer.start() self._mutex = QtCore.QMutex()
def _setup_pars(self): self.hue_min = self.parameter('hue-min').get() self.hue_max = self.parameter('hue-max').get() self.color_speed = self.parameter('color-speed').get() self.scale = self.parameter('scale').get() / 100.0 fade_colors = ast.literal_eval(self.parameter('luminance-map').get()) self.lum_fader = ColorFade(fade_colors, self._luminance_steps)
def update_fft_data(self, latest_fft): if len(latest_fft) == 0: print "received no fft" return #latest_fft = np.asarray(latest_fft) # noise_threshold = 0.1 # np.multiply(latest_fft, 1.0 + noise_threshold, latest_fft) # np.maximum(latest_fft - noise_threshold, 0.0, latest_fft) #latest_fft = latest_fft * (1.0 + noise_threshold) - noise_threshold if len(self.fft[0]) <= 1: self.fft[0] = latest_fft self.smoothed = np.asarray(latest_fft) self.peak[0] = np.max(latest_fft) self.peakFrequency[0] = np.argmax(latest_fft) self.average[0] = self.getEnergy() #print "first fft" return self.peak.insert(0, np.max(latest_fft)) self.average.insert(0, self.getEnergy()) self.fft.insert(0, latest_fft) self.peakFrequency.insert(0, np.argmax(latest_fft)) maxPeak = np.max(self.peak) if maxPeak > 1 / self.maxGain: self.gain = 1 / maxPeak else: self.gain = self.maxGain if len(self.fft) > 60: self.fft.pop() self.peak.pop() self.average.pop() self.peakFrequency.pop() colors = np.zeros((len(self.average), 3)) colors[:, 1] = self.average colors[:, 0] = np.multiply(self.peakFrequency, 1.0 / 255) self.fader = ColorFade(colors, self._fader_steps) # self.average.pop() # averageEnergy = np.sum(self.average) / len(self.fft) smoothing = 0.8 #np.insert(self.smoothed, 0, 0) #self.smoothed.pop() #self.smoothed *= 0.95 #= np.minimum(self.smoothed - 0.1) np.multiply(self.smoothed, 0.97, self.smoothed) self.smoothed = np.maximum(self.smoothed, latest_fft, self.smoothed) #np.multiply(latest_fft, 1 - smoothing) + np.multiply(self.smoothed, smoothing) self.smoothEnergy *= 0.9 #self.smoothEnergy = min(1.0, self.smoothEnergy + self.getEnergy()) self.smoothEnergy = max(self.smoothEnergy, self.getEnergy())
def _setup_pars(self): self.hue_min = self.parameter('hue-min').get() self.hue_max = self.parameter('hue-max').get() self.color_speed = self.parameter('color-speed').get() self.scale = self.parameter('scale').get() / 100.0 fade_colors = ast.literal_eval(self.parameter('lightness-map').get()) self.lum_fader = ColorFade(fade_colors, self._lightness_steps) angle = self.parameter('angle').get() rotMatrix = np.array([(math.cos(angle), -math.sin(angle)), (math.sin(angle), math.cos(angle))]) pixel_locations = np.asarray(self.scene().get_all_pixel_locations()) self._offset_x, self._offset_y = rotMatrix.T.dot(pixel_locations.T)
def __init__(self, app): self.fft = [[0]] self.smoothed = [] self.average = [[0]] self.peak = [[0]] self.peakFrequency = [[0]] self.gain = 1.0 self.maxGain = 5.0 self.fader = ColorFade([(0, 0, 1), (0, 1, 1)], self._fader_steps) self.pitch = 0.0 self.pitch_confidence = 0.0 self.smoothEnergy = 0.0
def _setup_colors(self): self._fader = ColorFade([ self.parameter('black-color').get(), self.parameter('off-color').get(), self.parameter('on-color').get() ], self._fader_steps)
class Twinkle(RawPreset): """Random pixels fade in and out""" _fading_up = [] _fading_down = [] _time = {} _fader = None def setup(self): random.seed() self.add_parameter(FloatParameter('birth-rate', 0.15)) self.add_parameter(FloatParameter('fade-up-time', 0.5)) self.add_parameter(FloatParameter('fade-down-time', 4.0)) self.add_parameter(HSVParameter('on-color', (0.1, 1.0, 1.0))) self.add_parameter(HSVParameter('off-color', (1.0, 0.0, 0.0))) self._setup_colors() def parameter_changed(self, parameter): if str(parameter) == 'on-color': self._setup_colors() def _setup_colors(self): self._up_target_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('on-color').get())) self._down_target_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('off-color').get())) self._fader = ColorFade('hsv', [ self.parameter('off-color').get(), self.parameter('on-color').get() ]) def reset(self): self._fading_up = [] self._fading_down = [] self._time = {} def draw(self, dt): # Birth if self._mixer.is_onset(): pbirth = 1.0 nbirth = 25 else: pbirth = self.parameter('birth-rate').get() nbirth = 1 for i in range(nbirth): if random.random() > (1.0 - pbirth): address = (random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), random.randint(0, self._max_pixel - 1)) if address not in self._fading_up: self._fading_up.append(address) self._time[address] = dt # Growth for address in self._fading_up: color = self._get_next_color(address, dt) if color == self._up_target_rgb: self._fading_up.remove(address) self._fading_down.append(address) self._time[address] = dt self.setp(address, color) # Decay for address in self._fading_down: color = self._get_next_color(address, dt, down=True) if color == self._down_target_rgb: self._fading_down.remove(address) self.setp(address, color) def _get_next_color(self, address, dt, down=False): time_target = float( self.parameter('fade-down-time').get()) if down else float( self.parameter('fade-up-time').get()) progress = (dt - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif dt == self._time[address]: progress = 0.0 if down: progress = 1.0 - progress return self._fader.get_color(progress)
class Dragons(RawPreset): """ Dragons spawn randomly and travel. At vertices, dragons can reproduce. If two dragons collide, both die. """ # Configurable parameters _alive_color = (0.5, 0.0, 1.0) # HSV _tail_color = (0.0, 1.0, 1.0) _dead_color = (1.0, 1.0, 0.0) # HSV _spontaneous_birth_probability = 0.0001 # Internal parameters class Dragon: def __init__(self, loc, dir, lifetime): self.loc = loc self.dir = dir self.lifetime = lifetime self.growing = True self.alive = False self.moving = False def __repr__(self): ds = 'Fwd' if self.dir == 1 else 'Rev' return "Dragon (%d, %d, %d) %s: %0.2f" % (self.loc[0], self.loc[1], self.loc[2], ds, self.lifetime) _dragons = [] _tails = [] _alive_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_alive_color)) _tail_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_tail_color)) _dead_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_dead_color)) _pop = 0 def setup(self): random.seed() self.add_parameter(FloatParameter('growth-time', 2.0)) self.add_parameter(FloatParameter('birth-rate', 0.4)) self.add_parameter(FloatParameter('tail-persist', 0.5)) self.add_parameter(IntParameter('pop-limit', 20)) self.add_parameter(HSVParameter('alive-color', self._alive_color)) self.add_parameter(HSVParameter('dead-color', self._dead_color)) self.add_parameter(HSVParameter('tail-color', self._tail_color)) self._setup_colors() def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._growth_fader = ColorFade('hsv', [(0., 0., 0.), self._alive_color], tick_rate=self._mixer.get_tick_rate()) self._tail_fader = ColorFade('hsv', [self._alive_color, self._tail_color, (0., 0., 0.)], tick_rate=self._mixer.get_tick_rate()) def parameter_changed(self, parameter): self._setup_colors() def draw(self, dt): # Ensure that empty displays start up with some dragons p_birth = (1.0 - self._spontaneous_birth_probability) if self._pop > 2 else 0.5 # Spontaneous birth: Rare after startup if (self._pop < self.parameter('pop-limit').get()) and random.random() > p_birth: address = ( random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), 0) if address not in [d.loc for d in self._dragons]: self._dragons.append(self.Dragon(address, 1, dt)) self._pop += 1 # Dragon life cycle for dragon in self._dragons: # Fade in if dragon.growing: p = (dt - dragon.lifetime) / self.parameter('growth-time').get() if (p > 1): p = 1.0 color = self._growth_fader.get_color(p) if p >= 1.0: dragon.growing = False dragon.alive = True dragon.lifetime = dt self.setp(dragon.loc, color) # Alive - can move or die if dragon.alive: s, f, p = dragon.loc self.setp(dragon.loc, (0, 0, 0)) # At a vertex: optionally spawn new dragons if dragon.moving and (p == 0 or p == (self.scene().fixture(s, f).pixels - 1)): if (self._pop < self.parameter('pop-limit').get()): neighbors = self.scene().get_pixel_neighbors(dragon.loc) random.shuffle(neighbors) # Iterate over candidate pixels that aren't on the current fixture num_children = 0 for candidate in [n for n in neighbors if n[1] != f]: if num_children == 0: # Spawn at least one new dragon to replace the old one. This first one skips the growth. dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(candidate, dir, dt) child.growing = False child.alive = True child.moving = False self._dragons.append(child) self._pop += 1 num_children += 1 else: # Randomly spawn new dragons if random.random() > (1.0 - self.parameter('birth-rate').get()): dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(candidate, dir, dt) child.moving = False self._dragons.append(child) self._pop += 1 num_children += 1 # Kill dragons that reach the end of a fixture dragon.moving = False self._dragons.remove(dragon) self._pop -= 1 else: # Move dragons along the fixture self._tails.append((dragon.loc, dt)) new_address = (s, f, p + dragon.dir) if new_address[2] < 0 or new_address[2] > 31: print dragon, "new_address", new_address assert(False) dragon.loc = new_address dragon.moving = True self.setp(new_address, self._alive_color_rgb) # Kill dragons that run into each other if dragon in self._dragons: colliding = [d for d in self._dragons if d != dragon and d.loc == dragon.loc] if len(colliding) > 0: #print "collision between", dragon, "and", colliding[0] self.setp(dragon.loc, (0, 0, 0)) self._dragons.remove(dragon) self._dragons.remove(colliding[0]) self.setp(dragon.loc, (0, 0, 0)) self._pop -= 2 # Draw tails for loc, time in self._tails: if (dt - time) > self.parameter('tail-persist').get(): self._tails.remove((loc, time)) self.setp(loc, (0, 0, 0)) else: progress = (dt - time) / self.parameter('tail-persist').get() self.setp(loc, self._tail_fader.get_color(progress))
class Dragons(RawPreset): """ Dragons spawn randomly and travel. At vertices, dragons can reproduce. If two dragons collide, both die. """ # Configurable parameters _alive_color = (0.0, 1.0, 1.0) _tail_color = (0.5, 0.0, 1.0) _dead_color = (0.0, 0.0, 0.0) _explode_color = (1.0, 1.0, 1.0) _fader_steps = 256 # Internal parameters class Dragon: def __init__(self, loc, dir, lifetime): self.loc = loc self.dir = dir self.lifetime = lifetime self.growing = True self.alive = False self.moving = False self.growth = 0 def __repr__(self): ds = 'Fwd' if self.dir == 1 else 'Rev' return "Dragon (%d, %d, %d) %s: %0.2f" % ( self.loc[0], self.loc[1], self.loc[2], ds, self.lifetime) def setup(self): self._dragons = [] self._tails = [] self.init_pixels() random.seed() self._current_time = 0 self.add_parameter(FloatParameter('growth-time', 2.0)) self.add_parameter(FloatParameter('birth-rate', 0.4)) self.add_parameter(FloatParameter('tail-persist', 0.5)) self.add_parameter(FloatParameter('growth-rate', 1.0)) self.add_parameter(IntParameter('pop-limit', 20)) self.add_parameter(HLSParameter('alive-color', self._alive_color)) self.add_parameter(HLSParameter('dead-color', self._dead_color)) self.add_parameter(HLSParameter('tail-color', self._tail_color)) self.add_parameter(HLSParameter('explode-color', self._explode_color)) self._setup_colors() def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() self._explode_color = self.parameter('explode-color').get() self._growth_fader = ColorFade([(0., 0., 0.), self._alive_color], self._fader_steps) self._tail_fader = ColorFade( [self._alive_color, self._tail_color, (0., 0., 0.)], self._fader_steps) self._explode_fader = ColorFade([self._explode_color, (0., 0., 0.)], self._fader_steps) def parameter_changed(self, parameter): self._setup_colors() def draw(self, dt): self._current_time += dt # Spontaneous birth: Rare after startup if (len(self._dragons) < self.parameter('pop-limit').get() ) and random.random() < self.parameter('birth-rate').get(): address = BufferUtils.logical_to_index( (random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), 0)) if address not in [d.loc for d in self._dragons]: self._dragons.append( self.Dragon(address, 1, self._current_time)) growth_rate = self.parameter('growth-rate').get() # Dragon life cycle for dragon in self._dragons: # Fade in if dragon.growing: p = (self._current_time - dragon.lifetime) / self.parameter('growth-time').get() if (p > 1): p = 1.0 color = self._growth_fader.get_color(p * self._fader_steps) if p >= 1.0: dragon.growing = False dragon.alive = True dragon.lifetime = self._current_time self.setPixelHLS(dragon.loc, color) # Alive - can move or die if dragon.alive: dragon.growth += dt * growth_rate for times in range(int(dragon.growth)): s, f, p = BufferUtils.index_to_logical(dragon.loc) self.setPixelHLS(dragon.loc, (0, 0, 0)) if random.random() < dragon.growth: dragon.growth -= 1 # At a vertex: optionally spawn new dragons if dragon.moving and (p == 0 or p == ( self.scene().fixture(s, f).pixels - 1)): neighbors = self.scene().get_pixel_neighbors( dragon.loc) neighbors = [ BufferUtils.index_to_logical(n) for n in neighbors ] random.shuffle(neighbors) # Kill dragons that reach the end of a fixture dragon.moving = False if dragon in self._dragons: self._dragons.remove(dragon) # Iterate over candidate pixels that aren't on the current fixture num_children = 0 for candidate in [ n for n in neighbors if n[1] != f ]: child_index = BufferUtils.logical_to_index( candidate) if num_children == 0: # Spawn at least one new dragon to replace the old one. This first one skips the growth. dir = 1 if candidate[2] == 0 else -1 child = self.Dragon( child_index, dir, self._current_time) child.growing = False child.alive = True child.moving = False self._dragons.append(child) num_children += 1 elif (len(self._dragons) < self.parameter('pop-limit').get()): # Randomly spawn new dragons if random.random() < self.parameter( 'birth-rate').get(): dir = 1 if candidate[2] == 0 else -1 child = self.Dragon( child_index, dir, self._current_time) child.moving = False self._dragons.append(child) num_children += 1 break else: # Move dragons along the fixture self._tails.append((dragon.loc, self._current_time, self._tail_fader)) new_address = BufferUtils.logical_to_index( (s, f, p + dragon.dir)) dragon.loc = new_address dragon.moving = True self.setPixelHLS(new_address, self._alive_color) # Kill dragons that run into each other if dragon in self._dragons: colliding = [ d for d in self._dragons if d != dragon and d.loc == dragon.loc ] if len(colliding) > 0: #print "collision between", dragon, "and", colliding[0] self._dragons.remove(dragon) self._dragons.remove(colliding[0]) self._tails.append((dragon.loc, self._current_time, self._explode_fader)) neighbors = self.scene().get_pixel_neighbors( dragon.loc) for neighbor in neighbors: self._tails.append( (neighbor, self._current_time, self._explode_fader)) break # Draw tails for loc, time, fader in self._tails: if (self._current_time - time) > self.parameter('tail-persist').get(): if (loc, time, fader) in self._tails: self._tails.remove((loc, time, fader)) self.setPixelHLS(loc, (0, 0, 0)) else: progress = (self._current_time - time) / self.parameter('tail-persist').get() self.setPixelHLS(loc, fader.get_color(progress * self._fader_steps))
def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._black_color = self.parameter('black-color').get() fade_colors = [self._black_color, self._alive_color, self._dead_color, self._black_color] self._fader = ColorFade(fade_colors, self._fader_steps)
def _setup_colors(self): self._alive_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('alive-color').get())) self._dead_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('dead-color').get())) fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._fader = ColorFade('hsv', fade_colors, tick_rate=self._mixer.get_tick_rate())
class Twinkle(RawPreset): """Random pixels fade in and out""" _fading_up = [] _fading_down = [] _time = {} _fader = None _fader_steps = 256 def setup(self): random.seed() self.add_parameter(FloatParameter('birth-rate', 0.15)) self.add_parameter(FloatParameter('fade-up-time', 0.5)) self.add_parameter(FloatParameter('fade-down-time', 4.0)) self.add_parameter(HLSParameter('on-color', (0.1, 1.0, 1.0))) self.add_parameter(HLSParameter('off-color', (1.0, 0.0, 1.0))) self.add_parameter(HLSParameter('beat-color', (1.0, 1.0, 1.0))) self.add_parameter(FloatParameter('beat-births', 25.0)) self.add_parameter(HLSParameter('black-color', (0.0, 0.0, 1.0))) self._setup_colors() self._nbirth = 0; self._current_time = 0; def parameter_changed(self, parameter): self._setup_colors() def _setup_colors(self): self._fader = ColorFade([self.parameter('black-color').get(), self.parameter('off-color').get(), self.parameter('on-color').get()], self._fader_steps) def reset(self): self._fading_up = [] self._fading_down = [] self._idle = self.scene().get_all_pixels()[:] self._time = {} def draw(self, dt): self._current_time += dt # Birth if self._mixer.is_onset(): self._nbirth += self.parameter('beat-births').get() self._nbirth += self.parameter('birth-rate').get() * dt for i in range(int(self._nbirth)): if random.random() < self._nbirth: if (len(self._idle) > 0): address = self._idle.pop(random.randint(0, len(self._idle) - 1)) self._fading_up.append(address) self._time[address] = self._current_time self._nbirth -= 1 # Growth for address in self._fading_up: progress = (self._current_time - self._time[address]) / float(self.parameter('fade-up-time').get()) * self._fader_steps color = self._fader.get_color(progress) if progress >= self._fader_steps: self._fading_up.remove(address) self._fading_down.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Decay for address in self._fading_down: progress = (1.0 - (self._current_time - self._time[address]) / float(self.parameter('fade-down-time').get())) * self._fader_steps color = self._fader.get_color(progress) if progress <= 0: self._idle.append(address) self._fading_down.remove(address) elif self._mixer.is_onset(): color = self.parameter('beat-color').get() self.setPixelHLS(address, color)
def _setup_colors(self): #fade_colors = [self.parameter('black-color').get(), self.parameter('off-color').get(), self.parameter('on-color').get()] fade_colors = ast.literal_eval(self.parameter('color-gradient').get()) self._fader = ColorFade(fade_colors, self._fader_steps)
class Dragons(RawPreset): """ Dragons spawn randomly and travel. At vertices, dragons can reproduce. If two dragons collide, both die. """ # Configurable parameters _alive_color = (0.0, 1.0, 1.0) _tail_color = (0.5, 0.0, 1.0) _dead_color = (0.0, 0.0, 0.0) _explode_color = (1.0, 1.0, 1.0) _fader_steps = 256 # Internal parameters class Dragon: def __init__(self, loc, dir, lifetime): self.loc = loc self.dir = dir self.lifetime = lifetime self.growing = True self.alive = False self.moving = False self.growth = 0 def __repr__(self): ds = 'Fwd' if self.dir == 1 else 'Rev' return "Dragon (%d, %d, %d) %s: %0.2f" % (self.loc[0], self.loc[1], self.loc[2], ds, self.lifetime) def setup(self): self._dragons = [] self._tails = [] self.init_pixels() random.seed() self._current_time = 0 self.add_parameter(FloatParameter('growth-time', 2.0)) self.add_parameter(FloatParameter('birth-rate', 0.4)) self.add_parameter(FloatParameter('tail-persist', 0.5)) self.add_parameter(FloatParameter('growth-rate', 1.0)) self.add_parameter(IntParameter('pop-limit', 20)) self.add_parameter(HLSParameter('alive-color', self._alive_color)) self.add_parameter(HLSParameter('dead-color', self._dead_color)) self.add_parameter(HLSParameter('tail-color', self._tail_color)) self.add_parameter(HLSParameter('explode-color', self._explode_color)) self._setup_colors() def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() self._explode_color = self.parameter('explode-color').get() self._growth_fader = ColorFade([(0., 0., 0.), self._alive_color], self._fader_steps) self._tail_fader = ColorFade([self._alive_color, self._tail_color, (0., 0., 0.)], self._fader_steps) self._explode_fader = ColorFade([self._explode_color, (0., 0., 0.)], self._fader_steps) def parameter_changed(self, parameter): self._setup_colors() def draw(self, dt): self._current_time += dt # Spontaneous birth: Rare after startup if (len(self._dragons) < self.parameter('pop-limit').get()) and random.random() < self.parameter('birth-rate').get(): strand = random.randint(0, BufferUtils.num_strands - 1) fixture = random.randint(0, BufferUtils.strand_num_fixtures(strand) - 1) address = BufferUtils.logical_to_index((strand, fixture, 0)) if address not in [d.loc for d in self._dragons]: self._dragons.append(self.Dragon(address, 1, self._current_time)) growth_rate = self.parameter('growth-rate').get() # Dragon life cycle for dragon in self._dragons: # Fade in if dragon.growing: p = (self._current_time - dragon.lifetime) / self.parameter('growth-time').get() if (p > 1): p = 1.0 color = self._growth_fader.get_color(p * self._fader_steps) if p >= 1.0: dragon.growing = False dragon.alive = True dragon.lifetime = self._current_time self.setPixelHLS(dragon.loc, color) # Alive - can move or die if dragon.alive: dragon.growth += dt * growth_rate for times in range(int(dragon.growth)): s, f, p = BufferUtils.index_to_logical(dragon.loc) self.setPixelHLS(dragon.loc, (0, 0, 0)) if random.random() < dragon.growth: dragon.growth -= 1 # At a vertex: optionally spawn new dragons if dragon.moving and (p == 0 or p == (self.scene().fixture(s, f).pixels - 1)): neighbors = self.scene().get_pixel_neighbors(dragon.loc) neighbors = [BufferUtils.index_to_logical(n) for n in neighbors] random.shuffle(neighbors) # Kill dragons that reach the end of a fixture dragon.moving = False if dragon in self._dragons: self._dragons.remove(dragon) # Iterate over candidate pixels that aren't on the current fixture num_children = 0 for candidate in [n for n in neighbors if n[1] != f]: child_index = BufferUtils.logical_to_index(candidate) if num_children == 0: # Spawn at least one new dragon to replace the old one. This first one skips the growth. dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(child_index, dir, self._current_time) child.growing = False child.alive = True child.moving = False self._dragons.append(child) num_children += 1 elif (len(self._dragons) < self.parameter('pop-limit').get()): # Randomly spawn new dragons if random.random() < self.parameter('birth-rate').get(): dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(child_index, dir, self._current_time) child.moving = False self._dragons.append(child) num_children += 1 break; else: # Move dragons along the fixture self._tails.append((dragon.loc, self._current_time, self._tail_fader)) new_address = BufferUtils.logical_to_index((s, f, p + dragon.dir)) dragon.loc = new_address dragon.moving = True self.setPixelHLS(new_address, self._alive_color) # Kill dragons that run into each other if dragon in self._dragons: colliding = [d for d in self._dragons if d != dragon and d.loc == dragon.loc] if len(colliding) > 0: #print "collision between", dragon, "and", colliding[0] self._dragons.remove(dragon) self._dragons.remove(colliding[0]) self._tails.append((dragon.loc, self._current_time, self._explode_fader)) neighbors = self.scene().get_pixel_neighbors(dragon.loc) for neighbor in neighbors: self._tails.append((neighbor, self._current_time, self._explode_fader)) break # Draw tails for loc, time, fader in self._tails: if (self._current_time - time) > self.parameter('tail-persist').get(): if (loc, time, fader) in self._tails: self._tails.remove((loc, time, fader)) self.setPixelHLS(loc, (0, 0, 0)) else: progress = (self._current_time - time) / self.parameter('tail-persist').get() self.setPixelHLS(loc, fader.get_color(progress * self._fader_steps))
def __init__(self, audio_emitter, fade_colors, fade_steps): self.audio_emitter = audio_emitter self._fader = ColorFade(fade_colors, fade_steps) self.value = 0.0 self.color = 0
class Dragons(RawPreset): """ Dragons spawn randomly and travel. At vertices, dragons can reproduce. If two dragons collide, both die. """ # Configurable parameters _alive_color = (0.5, 0.0, 1.0) # HSV _tail_color = (0.0, 1.0, 1.0) _dead_color = (1.0, 1.0, 0.0) # HSV _spontaneous_birth_probability = 0.0001 # Internal parameters class Dragon: def __init__(self, loc, dir, lifetime): self.loc = loc self.dir = dir self.lifetime = lifetime self.growing = True self.alive = False self.moving = False def __repr__(self): ds = 'Fwd' if self.dir == 1 else 'Rev' return "Dragon (%d, %d, %d) %s: %0.2f" % ( self.loc[0], self.loc[1], self.loc[2], ds, self.lifetime) _dragons = [] _tails = [] _alive_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_alive_color)) _tail_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_tail_color)) _dead_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*_dead_color)) _pop = 0 def setup(self): random.seed() self.add_parameter(FloatParameter('growth-time', 2.0)) self.add_parameter(FloatParameter('birth-rate', 0.4)) self.add_parameter(FloatParameter('tail-persist', 0.5)) self.add_parameter(IntParameter('pop-limit', 20)) self.add_parameter(HSVParameter('alive-color', self._alive_color)) self.add_parameter(HSVParameter('dead-color', self._dead_color)) self.add_parameter(HSVParameter('tail-color', self._tail_color)) self._setup_colors() def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._tail_color = self.parameter('tail-color').get() fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._growth_fader = ColorFade('hsv', [(0., 0., 0.), self._alive_color], tick_rate=self._mixer.get_tick_rate()) self._tail_fader = ColorFade( 'hsv', [self._alive_color, self._tail_color, (0., 0., 0.)], tick_rate=self._mixer.get_tick_rate()) def parameter_changed(self, parameter): self._setup_colors() def draw(self, dt): # Ensure that empty displays start up with some dragons p_birth = ( 1.0 - self._spontaneous_birth_probability) if self._pop > 2 else 0.5 # Spontaneous birth: Rare after startup if (self._pop < self.parameter('pop-limit').get() ) and random.random() > p_birth: address = (random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), 0) if address not in [d.loc for d in self._dragons]: self._dragons.append(self.Dragon(address, 1, dt)) self._pop += 1 # Dragon life cycle for dragon in self._dragons: # Fade in if dragon.growing: p = (dt - dragon.lifetime) / self.parameter('growth-time').get() if (p > 1): p = 1.0 color = self._growth_fader.get_color(p) if p >= 1.0: dragon.growing = False dragon.alive = True dragon.lifetime = dt self.setp(dragon.loc, color) # Alive - can move or die if dragon.alive: s, f, p = dragon.loc self.setp(dragon.loc, (0, 0, 0)) # At a vertex: optionally spawn new dragons if dragon.moving and (p == 0 or p == (self.scene().fixture(s, f).pixels - 1)): if (self._pop < self.parameter('pop-limit').get()): neighbors = self.scene().get_pixel_neighbors( dragon.loc) random.shuffle(neighbors) # Iterate over candidate pixels that aren't on the current fixture num_children = 0 for candidate in [n for n in neighbors if n[1] != f]: if num_children == 0: # Spawn at least one new dragon to replace the old one. This first one skips the growth. dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(candidate, dir, dt) child.growing = False child.alive = True child.moving = False self._dragons.append(child) self._pop += 1 num_children += 1 else: # Randomly spawn new dragons if random.random() > ( 1.0 - self.parameter('birth-rate').get()): dir = 1 if candidate[2] == 0 else -1 child = self.Dragon(candidate, dir, dt) child.moving = False self._dragons.append(child) self._pop += 1 num_children += 1 # Kill dragons that reach the end of a fixture dragon.moving = False self._dragons.remove(dragon) self._pop -= 1 else: # Move dragons along the fixture self._tails.append((dragon.loc, dt)) new_address = (s, f, p + dragon.dir) if new_address[2] < 0 or new_address[2] > 31: print dragon, "new_address", new_address assert (False) dragon.loc = new_address dragon.moving = True self.setp(new_address, self._alive_color_rgb) # Kill dragons that run into each other if dragon in self._dragons: colliding = [ d for d in self._dragons if d != dragon and d.loc == dragon.loc ] if len(colliding) > 0: #print "collision between", dragon, "and", colliding[0] self.setp(dragon.loc, (0, 0, 0)) self._dragons.remove(dragon) self._dragons.remove(colliding[0]) self.setp(dragon.loc, (0, 0, 0)) self._pop -= 2 # Draw tails for loc, time in self._tails: if (dt - time) > self.parameter('tail-persist').get(): self._tails.remove((loc, time)) self.setp(loc, (0, 0, 0)) else: progress = (dt - time) / self.parameter('tail-persist').get() self.setp(loc, self._tail_fader.get_color(progress))
class Fungus(RawPreset): """ Spreading fungus Illustrates use of Scene.get_pixel_neighbors. Fungal pixels go through three stages: Growing, Dying, and then Fading Out. """ _growing = [] _alive = [] _dying = [] _fading_out = [] # Configurable parameters _spontaneous_birth_probability = 0.0001 # Internal parameters _time = {} _pop = 0 _fader = None _growth_time = 0.6 _life_time = 1.0 _isolated_life_time = 1.0 _death_time = 7.0 _birth_rate = 0.05 _spread_rate = 0.25 _fade_out_time = 4.0 _mass_destruction_time = 10.0 _mass_destruction_threshold = 150 _pop_limit = 500 _alive_color = (1.0, 0.0, 1.0) _dead_color = (0.0, 1.0, 1.0) def setup(self): self._pop = 0 self._time = {} self.add_parameter(FloatParameter('growth-time', self._growth_time)) self.add_parameter(FloatParameter('life-time', self._life_time)) self.add_parameter( FloatParameter('isolated-life-time', self._isolated_life_time)) self.add_parameter(FloatParameter('death-time', self._death_time)) self.add_parameter(FloatParameter('birth-rate', self._birth_rate)) self.add_parameter(FloatParameter('spread-rate', self._spread_rate)) self.add_parameter(FloatParameter('fade-out-time', self._fade_out_time)) self.add_parameter( FloatParameter('mass-destruction-time', self._mass_destruction_time)) self.add_parameter( IntParameter('mass-destruction-threshold', self._mass_destruction_threshold)) self.add_parameter(IntParameter('pop-limit', self._pop_limit)) self.add_parameter(HSVParameter('alive-color', self._alive_color)) self.add_parameter(HSVParameter('dead-color', self._dead_color)) self.parameter_changed(None) def reset(self): self._growing = [] self._alive = [] self._dying = [] self._fading_out = [] self._pop = 0 self._time = {} self.parameter_changed(None) def parameter_changed(self, parameter): self._setup_colors() self._growth_time = self.parameter('growth-time').get() self._life_time = self.parameter('life-time').get() self._isolated_life_time = self.parameter('isolated-life-time').get() self._death_time = self.parameter('death-time').get() self._birth_rate = self.parameter('birth-rate').get() self._spread_rate = self.parameter('spread-rate').get() self._fade_out_time = self.parameter('fade-out-time').get() self._mass_destruction_time = self.parameter( 'mass-destruction-time').get() self._mass_destruction_threshold = self.parameter( 'mass-destruction-threshold').get() self._pop_limit = self._pop_limit def _setup_colors(self): self._alive_color_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('alive-color').get())) self._dead_color_rgb = float_to_uint8( colorsys.hsv_to_rgb(*self.parameter('dead-color').get())) fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._fader = ColorFade('hsv', fade_colors, tick_rate=self._mixer.get_tick_rate()) def draw(self, dt): # Ensure that empty displays start up with some seeds p_birth = ( 1.0 - self._spontaneous_birth_probability) if self._pop > 5 else 0.5 # Spontaneous birth: Rare after startup if (self._pop < self._pop_limit) and random.random() > p_birth: address = (random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), random.randint(0, self._max_pixel - 1)) if address not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(address) self._time[address] = dt self._pop += 1 # Color growth for address in self._growing: neighbors = self.scene().get_pixel_neighbors(address) p, color = self._get_next_color(address, self._growth_time, dt) if p >= 1.0: self._growing.remove(address) self._alive.append(address) self._time[address] = dt self.setp(address, color) # Spread if (self._pop < self._pop_limit ) and random.random() > (1.0 - self._spread_rate): spread = neighbors[random.randint(0, len(neighbors) - 1)] if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = dt self._pop += 1 # Lifetime for address in self._alive: neighbors = self.scene().get_pixel_neighbors(address) live_neighbors = [i for i in neighbors if i in self._alive] lt = self.parameter('life-time').get() if len(neighbors) < 2: lt = self._isolated_life_time if len(live_neighbors) < 2 and ( (dt - self._time[address]) / lt) >= 1.0: self._alive.remove(address) self._dying.append(address) self._time[address] = dt self._pop -= 1 self.setp(address, self._alive_color_rgb) # Spread if (self._pop < self._pop_limit ) and random.random() > (1.0 - self._birth_rate): spread = neighbors[random.randint(0, len(neighbors) - 1)] if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = dt self._pop += 1 # Color decay for address in self._dying: p, color = self._get_next_color(address, self._death_time, dt) if p >= 1.0: self._dying.remove(address) self._fading_out.append(address) self._time[address] = dt self.setp(address, color) # Fade out for address in self._fading_out: p, color = self._get_next_color(address, self._fade_out_time, dt) if p >= 1.0: self._fading_out.remove(address) self.setp(address, color) # Mass destruction if (self._pop == self._pop_limit) or \ (self._pop > self._mass_destruction_threshold and ((dt % self._mass_destruction_time) == 0)): for i in self._alive: if random.random() > 0.95: self._alive.remove(i) self._dying.append(i) self._pop -= 1 for i in self._growing: if random.random() > 0.85: self._growing.remove(i) self._dying.append(i) self._pop -= 1 def _get_next_color(self, address, time_target, dt): """ Returns the next color for a pixel, given the pixel's current state """ progress = (dt - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif dt == self._time[address]: progress = 0.0 idx = progress / 3.0 if time_target == self._death_time: idx += (1.0 / 3.0) elif time_target == self._fade_out_time: idx += (2.0 / 3.0) return (progress, self._fader.get_color(idx))
class SpiralGradient(RawPreset): """Spiral gradient that responds to onsets""" _fader = None _fader_resolution = 256 def setup(self): self.add_parameter(FloatParameter('speed', 0.3)) self.add_parameter(FloatParameter('hue-speed', 0.3)) self.add_parameter(FloatParameter('angle-hue-width', 2.0)) self.add_parameter(FloatParameter('radius-hue-width', 1.5)) self.add_parameter(FloatParameter('wave-hue-width', 0.1)) self.add_parameter(FloatParameter('wave-hue-period', 0.1)) self.add_parameter(FloatParameter('wave-speed', 0.1)) self.add_parameter(FloatParameter('hue-step', 0.1)) self.add_parameter(HLSParameter('color-start', (0.0, 0.5, 1.0))) self.add_parameter(HLSParameter('color-end', (1.0, 0.5, 1.0))) self.hue_inner = 0 self.color_offset = 0 self.wave_offset = random.random() self.pixels = self.scene().get_all_pixels() cx, cy = self.scene().get_centroid() # Find radius to each pixel self.pixel_distances = {} self.pixel_angles = {} for pixel in self.pixels: x, y = self.scene().get_pixel_location(pixel) dx = x - cx dy = y - cy d = math.sqrt(math.pow(dx, 2) + math.pow(dy, 2)) self.pixel_distances[pixel] = d self.pixel_angles[pixel] = (math.pi + math.atan2(dy, dx)) / (2.0 * math.pi) # Normalize max_distance = max(self.pixel_distances.values()) for pixel in self.pixels: self.pixel_distances[pixel] /= max_distance self.parameter_changed(None) def parameter_changed(self, parameter): fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] self._fader = ColorFade(fade_colors, self._fader_resolution) def reset(self): pass def draw(self, dt): if self._mixer.is_onset(): self.hue_inner = self.hue_inner + self.parameter('hue-step').get() self.hue_inner += dt * self.parameter('hue-speed').get() self.wave_offset += dt * self.parameter('wave-speed').get() self.color_offset += dt * self.parameter('speed').get() wave_hue_period = 2 * math.pi * self.parameter('wave-hue-period').get() wave_hue_width = self.parameter('wave-hue-width').get() radius_hue_width = self.parameter('radius-hue-width').get() angle_hue_width = self.parameter('angle-hue-width').get() for pixel in self.pixels: angle = math.fmod(1.0 + self.pixel_angles[pixel] + math.sin(self.wave_offset + self.pixel_distances[pixel] * wave_hue_period) * wave_hue_width, 1.0) hue = self.color_offset + (radius_hue_width * self.pixel_distances[pixel]) + (2 * abs(angle - 0.5) * angle_hue_width) hue = math.fmod(math.floor(hue * self._fader_resolution) / self._fader_resolution, 1.0) color = self._fader.get_color(hue) self.setPixelHLS(pixel, (color[0] + self.hue_inner, color[1], color[2]))
def parameter_changed(self, parameter): fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] self._fader = ColorFade(fade_colors, self._fader_resolution)
def _setup_colors(self): self._up_target_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('on-color').get())) self._down_target_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('off-color').get())) self._fader = ColorFade('hsv', [self.parameter('off-color').get(), self.parameter('on-color').get()])
class Fungus(Pattern): """ Spreading fungus Illustrates use of Scene.get_pixel_neighbors. Fungal pixels go through three stages: Growing, Dying, and then Fading Out. """ _growing = [] _alive = [] _dying = [] _fading_out = [] _fader_steps = 256 # Configurable parameters _spontaneous_birth_probability = 0.0001 # Internal parameters _time = {} _population = 0 _fader = None _growth_time = 0.6 _life_time = 0.5 _isolated_life_time = 1.0 _death_time = 3.0 _birth_rate = 0.05 _spread_rate = 0.25 _fade_out_time = 2.0 _mass_destruction_countdown = 2.0 _mass_destruction_threshold = 150 _population_limit = 500 _alive_color = (1.0, 1.0, 1.0) _dead_color = (0.0, 0.5, 1.0) _black_color = (0.0, 0.0, 1.0) def setup(self): self._population = 0 self._time = {} self.add_parameter(FloatParameter('audio-onset-spread-boost', 0.0)) self.add_parameter(FloatParameter('audio-onset-spread-boost-echo', 0.5)) self.add_parameter(FloatParameter('audio-onset-death-boost', 0.0)) self.add_parameter(FloatParameter('audio-onset-birth-boost', 0.0)) self.add_parameter(FloatParameter('growth-time', self._growth_time)) self.add_parameter(FloatParameter('life-time', self._life_time)) self.add_parameter( FloatParameter('isolated-life-time', self._isolated_life_time)) self.add_parameter(FloatParameter('death-time', self._death_time)) self.add_parameter(FloatParameter('birth-rate', self._birth_rate)) self.add_parameter(FloatParameter('spread-rate', self._spread_rate)) self.add_parameter(FloatParameter('fade-out-time', self._fade_out_time)) self.add_parameter( FloatParameter('mass-destruction-time', self._mass_destruction_countdown)) self.add_parameter( IntParameter('mass-destruction-threshold', self._mass_destruction_threshold)) self.add_parameter(IntParameter('pop-limit', self._population_limit)) self.add_parameter(HLSParameter('alive-color', self._alive_color)) self.add_parameter(HLSParameter('dead-color', self._dead_color)) self.add_parameter(HLSParameter('black-color', self._black_color)) super(Fungus, self).setup() def reset(self): self._current_time = 0 self._growing = [] self._alive = [] self._dying = [] self._fading_out = [] self._population = 0 self._time = {} self._spread_boost = 0 self.parameter_changed(None) def parameter_changed(self, parameter): self._setup_colors() self._growth_time = self.parameter('growth-time').get() self._life_time = self.parameter('life-time').get() self._isolated_life_time = self.parameter('isolated-life-time').get() self._death_time = self.parameter('death-time').get() self._birth_rate = self.parameter('birth-rate').get() self._spread_rate = self.parameter('spread-rate').get() self._fade_out_time = self.parameter('fade-out-time').get() self._mass_destruction_countdown = self.parameter( 'mass-destruction-time').get() self._mass_destruction_threshold = self.parameter( 'mass-destruction-threshold').get() self._population_limit = self._population_limit def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._black_color = self.parameter('black-color').get() fade_colors = [ self._black_color, self._alive_color, self._dead_color, self._black_color ] self._fader = ColorFade(fade_colors, self._fader_steps) def draw(self, dt): self._current_time += dt self._mass_destruction_countdown -= dt # Ensure that empty displays start up with some seeds p_birth = (1.0 - self._spontaneous_birth_probability ) if self._population > 5 else 0.5 # Spontaneous birth: Rare after startup if (self._population < self._population_limit) and random.random( ) + self.parameter('audio-onset-birth-boost').get() > p_birth: strand = random.randint(0, BufferUtils.num_strands - 1) fixture = random.randint( 0, BufferUtils.strand_num_fixtures(strand) - 1) pixel = random.randint( 0, BufferUtils.fixture_length(strand, fixture) - 1) address = BufferUtils.logical_to_index((strand, fixture, pixel)) if address not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(address) self._time[address] = self._current_time self._population += 1 self._spread_boost *= self.parameter( 'audio-onset-spread-boost-echo').get() if self._mixer.is_onset(): self._spread_boost += self.parameter( 'audio-onset-spread-boost').get() # Color growth for address in self._growing: neighbors = self.scene().get_pixel_neighbors(address) p, color = self._get_next_color(address, self._growth_time, self._current_time) if p >= 1.0: self._growing.remove(address) self._alive.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Spread spread_rate = self._spread_rate + self._spread_boost if (self._population < self._population_limit) and ( random.random() < spread_rate * dt): for spread in neighbors: if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = self._current_time self._population += 1 # Lifetime for address in self._alive: neighbors = self.scene().get_pixel_neighbors(address) live_neighbors = [i for i in neighbors if i in self._alive] lt = self._life_time if len(neighbors) < 2: lt = self._isolated_life_time if len(live_neighbors) < 3 and ( (self._current_time - self._time[address]) / lt) >= 1.0: self._alive.remove(address) self._dying.append(address) self._time[address] = self._current_time self._population -= 1 self.setPixelHLS(address, self._alive_color) # Spread if (self._population < self._population_limit ) and random.random() < self._birth_rate * dt: for spread in neighbors: if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = self._current_time self._population += 1 # Color decay for address in self._dying: p, color = self._get_next_color( address, self._death_time, self._current_time + self.parameter('audio-onset-death-boost').get()) if p >= 1.0: self._dying.remove(address) self._fading_out.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Fade out for address in self._fading_out: p, color = self._get_next_color( address, self._fade_out_time, self._current_time + self.parameter('audio-onset-death-boost').get()) if p >= 1.0: self._fading_out.remove(address) self.setPixelHLS(address, color) # Mass destruction if (self._population == self._population_limit) or \ (self._population > self._mass_destruction_threshold and self._mass_destruction_countdown <= 0): for i in self._alive: if random.random() > 0.95: self._alive.remove(i) self._dying.append(i) self._population -= 1 for i in self._growing: if random.random() > 0.85: self._growing.remove(i) self._dying.append(i) self._population -= 1 self._mass_destruction_countdown = self.parameter( 'mass-destruction-time').get() def _get_next_color(self, address, time_target, current_time): """ Returns the next color for a pixel, given the pixel's current state """ progress = (current_time - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif current_time == self._time[address]: progress = 0.0 idx = progress / 3.0 if time_target == self._death_time: idx += (1.0 / 3.0) elif time_target == self._fade_out_time: idx += (2.0 / 3.0) return (progress, self._fader.get_color(idx * self._fader_steps))
def _setup_colors(self): self._up_target = self.parameter('on-color').get() self._down_target = self.parameter('off-color').get() self._fader = ColorFade([self.parameter('off-color').get(), self.parameter('on-color').get()])
def _setup_colors(self): self._fader = ColorFade([self.parameter('black-color').get(), self.parameter('off-color').get(), self.parameter('on-color').get()], self._fader_steps)
class Twinkle(RawPreset): """Random pixels fade in and out""" _fading_up = [] _fading_down = [] _time = {} _fader = None def setup(self): random.seed() self.add_parameter(FloatParameter('birth-rate', 0.15)) self.add_parameter(FloatParameter('fade-up-time', 0.5)) self.add_parameter(FloatParameter('fade-down-time', 4.0)) self.add_parameter(HSVParameter('on-color', (0.1, 1.0, 1.0))) self.add_parameter(HSVParameter('off-color', (1.0, 0.0, 0.0))) self._setup_colors() def parameter_changed(self, parameter): if str(parameter) == 'on-color': self._setup_colors() def _setup_colors(self): self._up_target_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('on-color').get())) self._down_target_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('off-color').get())) self._fader = ColorFade('hsv', [self.parameter('off-color').get(), self.parameter('on-color').get()]) def reset(self): self._fading_up = [] self._fading_down = [] self._time = {} def draw(self, dt): # Birth if self._mixer.is_onset(): pbirth = 1.0 nbirth = 25 else: pbirth = self.parameter('birth-rate').get() nbirth = 1 for i in range(nbirth): if random.random() > (1.0 - pbirth): address = ( random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), random.randint(0, self._max_pixel - 1)) if address not in self._fading_up: self._fading_up.append(address) self._time[address] = dt # Growth for address in self._fading_up: color = self._get_next_color(address, dt) if color == self._up_target_rgb: self._fading_up.remove(address) self._fading_down.append(address) self._time[address] = dt self.setp(address, color) # Decay for address in self._fading_down: color = self._get_next_color(address, dt, down=True) if color == self._down_target_rgb: self._fading_down.remove(address) self.setp(address, color) def _get_next_color(self, address, dt, down=False): time_target = float(self.parameter('fade-down-time').get()) if down else float(self.parameter('fade-up-time').get()) progress = (dt - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif dt == self._time[address]: progress = 0.0 if down: progress = 1.0 - progress return self._fader.get_color(progress)
class Fungus(RawPreset): """ Spreading fungus Illustrates use of Scene.get_pixel_neighbors. Fungal pixels go through three stages: Growing, Dying, and then Fading Out. """ _growing = [] _alive = [] _dying = [] _fading_out = [] # Configurable parameters _spontaneous_birth_probability = 0.0001 # Internal parameters _time = {} _pop = 0 _fader = None _growth_time = 0.6 _life_time = 1.0 _isolated_life_time = 1.0 _death_time = 7.0 _birth_rate = 0.05 _spread_rate = 0.25 _fade_out_time = 4.0 _mass_destruction_time = 10.0 _mass_destruction_threshold = 150 _pop_limit = 500 _alive_color = (1.0, 0.0, 1.0) _dead_color = (0.0, 1.0, 1.0) def setup(self): self._pop = 0 self._time = {} self.add_parameter(FloatParameter('growth-time', self._growth_time)) self.add_parameter(FloatParameter('life-time', self._life_time)) self.add_parameter(FloatParameter('isolated-life-time', self._isolated_life_time)) self.add_parameter(FloatParameter('death-time', self._death_time)) self.add_parameter(FloatParameter('birth-rate', self._birth_rate)) self.add_parameter(FloatParameter('spread-rate', self._spread_rate)) self.add_parameter(FloatParameter('fade-out-time', self._fade_out_time)) self.add_parameter(FloatParameter('mass-destruction-time', self._mass_destruction_time)) self.add_parameter(IntParameter('mass-destruction-threshold', self._mass_destruction_threshold)) self.add_parameter(IntParameter('pop-limit', self._pop_limit)) self.add_parameter(HSVParameter('alive-color', self._alive_color)) self.add_parameter(HSVParameter('dead-color', self._dead_color)) self.parameter_changed(None) def reset(self): self._growing = [] self._alive = [] self._dying = [] self._fading_out = [] self._pop = 0 self._time = {} self.parameter_changed(None) def parameter_changed(self, parameter): self._setup_colors() self._growth_time = self.parameter('growth-time').get() self._life_time = self.parameter('life-time').get() self._isolated_life_time = self.parameter('isolated-life-time').get() self._death_time = self.parameter('death-time').get() self._birth_rate = self.parameter('birth-rate').get() self._spread_rate = self.parameter('spread-rate').get() self._fade_out_time = self.parameter('fade-out-time').get() self._mass_destruction_time = self.parameter('mass-destruction-time').get() self._mass_destruction_threshold = self.parameter('mass-destruction-threshold').get() self._pop_limit = self._pop_limit def _setup_colors(self): self._alive_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('alive-color').get())) self._dead_color_rgb = float_to_uint8(colorsys.hsv_to_rgb(*self.parameter('dead-color').get())) fade_colors = [(0., 0., 0.), self.parameter('alive-color').get(), self.parameter('dead-color').get(), (0., 0., 0.)] self._fader = ColorFade('hsv', fade_colors, tick_rate=self._mixer.get_tick_rate()) def draw(self, dt): # Ensure that empty displays start up with some seeds p_birth = (1.0 - self._spontaneous_birth_probability) if self._pop > 5 else 0.5 # Spontaneous birth: Rare after startup if (self._pop < self._pop_limit) and random.random() > p_birth: address = ( random.randint(0, self._max_strand - 1), random.randint(0, self._max_fixture - 1), random.randint(0, self._max_pixel - 1)) if address not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(address) self._time[address] = dt self._pop += 1 # Color growth for address in self._growing: neighbors = self.scene().get_pixel_neighbors(address) p, color = self._get_next_color(address, self._growth_time, dt) if p >= 1.0: self._growing.remove(address) self._alive.append(address) self._time[address] = dt self.setp(address, color) # Spread if (self._pop < self._pop_limit) and random.random() > (1.0 - self._spread_rate): spread = neighbors[random.randint(0, len(neighbors) - 1)] if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = dt self._pop += 1 # Lifetime for address in self._alive: neighbors = self.scene().get_pixel_neighbors(address) live_neighbors = [i for i in neighbors if i in self._alive] lt = self.parameter('life-time').get() if len(neighbors) < 2: lt = self._isolated_life_time if len(live_neighbors) < 2 and ((dt - self._time[address]) / lt) >= 1.0: self._alive.remove(address) self._dying.append(address) self._time[address] = dt self._pop -= 1 self.setp(address, self._alive_color_rgb) # Spread if (self._pop < self._pop_limit) and random.random() > (1.0 - self._birth_rate): spread = neighbors[random.randint(0, len(neighbors) - 1)] if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = dt self._pop += 1 # Color decay for address in self._dying: p, color = self._get_next_color(address, self._death_time, dt) if p >= 1.0: self._dying.remove(address) self._fading_out.append(address) self._time[address] = dt self.setp(address, color) # Fade out for address in self._fading_out: p, color = self._get_next_color(address, self._fade_out_time, dt) if p >= 1.0: self._fading_out.remove(address) self.setp(address, color) # Mass destruction if (self._pop == self._pop_limit) or \ (self._pop > self._mass_destruction_threshold and ((dt % self._mass_destruction_time) == 0)): for i in self._alive: if random.random() > 0.95: self._alive.remove(i) self._dying.append(i) self._pop -= 1 for i in self._growing: if random.random() > 0.85: self._growing.remove(i) self._dying.append(i) self._pop -= 1 def _get_next_color(self, address, time_target, dt): """ Returns the next color for a pixel, given the pixel's current state """ progress = (dt - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif dt == self._time[address]: progress = 0.0 idx = progress / 3.0 if time_target == self._death_time: idx += (1.0 / 3.0) elif time_target == self._fade_out_time: idx += (2.0 / 3.0) return (progress, self._fader.get_color(idx))
def parameter_changed(self, parameter): fade_colors = [self.parameter('color-start').get(), self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] # fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] # fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] self._fader = ColorFade(fade_colors, self.parameter('posterization').get())
class Fungus(Pattern): """ Spreading fungus Illustrates use of Scene.get_pixel_neighbors. Fungal pixels go through three stages: Growing, Dying, and then Fading Out. """ _growing = [] _alive = [] _dying = [] _fading_out = [] _fader_steps = 256 # Configurable parameters _spontaneous_birth_probability = 0.0001 # Internal parameters _time = {} _population = 0 _fader = None _growth_time = 0.6 _life_time = 0.5 _isolated_life_time = 1.0 _death_time = 3.0 _birth_rate = 0.05 _spread_rate = 0.25 _fade_out_time = 2.0 _mass_destruction_countdown = 2.0 _mass_destruction_threshold = 150 _population_limit = 500 _alive_color = (1.0, 1.0, 1.0) _dead_color = (0.0, 0.5, 1.0) _black_color = (0.0, 0.0, 1.0) def setup(self): self._population = 0 self._time = {} self.add_parameter(FloatParameter('audio-onset-spread-boost', 0.0)) self.add_parameter(FloatParameter('audio-onset-spread-boost-echo', 0.5)) self.add_parameter(FloatParameter('audio-onset-death-boost', 0.0)) self.add_parameter(FloatParameter('audio-onset-birth-boost', 0.0)) self.add_parameter(FloatParameter('growth-time', self._growth_time)) self.add_parameter(FloatParameter('life-time', self._life_time)) self.add_parameter(FloatParameter('isolated-life-time', self._isolated_life_time)) self.add_parameter(FloatParameter('death-time', self._death_time)) self.add_parameter(FloatParameter('birth-rate', self._birth_rate)) self.add_parameter(FloatParameter('spread-rate', self._spread_rate)) self.add_parameter(FloatParameter('fade-out-time', self._fade_out_time)) self.add_parameter(FloatParameter('mass-destruction-time', self._mass_destruction_countdown)) self.add_parameter(IntParameter('mass-destruction-threshold', self._mass_destruction_threshold)) self.add_parameter(IntParameter('pop-limit', self._population_limit)) self.add_parameter(HLSParameter('alive-color', self._alive_color)) self.add_parameter(HLSParameter('dead-color', self._dead_color)) self.add_parameter(HLSParameter('black-color', self._black_color)) super(Fungus, self).setup() def reset(self): self._current_time = 0 self._growing = [] self._alive = [] self._dying = [] self._fading_out = [] self._population = 0 self._time = {} self._spread_boost = 0 self.parameter_changed(None) def parameter_changed(self, parameter): self._setup_colors() self._growth_time = self.parameter('growth-time').get() self._life_time = self.parameter('life-time').get() self._isolated_life_time = self.parameter('isolated-life-time').get() self._death_time = self.parameter('death-time').get() self._birth_rate = self.parameter('birth-rate').get() self._spread_rate = self.parameter('spread-rate').get() self._fade_out_time = self.parameter('fade-out-time').get() self._mass_destruction_countdown = self.parameter('mass-destruction-time').get() self._mass_destruction_threshold = self.parameter('mass-destruction-threshold').get() self._population_limit = self._population_limit def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._black_color = self.parameter('black-color').get() fade_colors = [self._black_color, self._alive_color, self._dead_color, self._black_color] self._fader = ColorFade(fade_colors, self._fader_steps) def draw(self, dt): self._current_time += dt self._mass_destruction_countdown -= dt # Ensure that empty displays start up with some seeds p_birth = (1.0 - self._spontaneous_birth_probability) if self._population > 5 else 0.5 # Spontaneous birth: Rare after startup if (self._population < self._population_limit) and random.random() + self.parameter('audio-onset-birth-boost').get() > p_birth: strand = random.randint(0, BufferUtils.num_strands - 1) fixture = random.randint(0, BufferUtils.strand_num_fixtures(strand) - 1) pixel = random.randint(0, BufferUtils.fixture_length(strand, fixture) - 1) address = BufferUtils.logical_to_index((strand, fixture, pixel)) if address not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(address) self._time[address] = self._current_time self._population += 1 self._spread_boost *= self.parameter('audio-onset-spread-boost-echo').get() if self._mixer.is_onset(): self._spread_boost += self.parameter('audio-onset-spread-boost').get() # Color growth for address in self._growing: neighbors = self.scene().get_pixel_neighbors(address) p, color = self._get_next_color(address, self._growth_time, self._current_time) if p >= 1.0: self._growing.remove(address) self._alive.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Spread spread_rate = self._spread_rate + self._spread_boost if (self._population < self._population_limit) and (random.random() < spread_rate * dt): for spread in neighbors: if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = self._current_time self._population += 1 # Lifetime for address in self._alive: neighbors = self.scene().get_pixel_neighbors(address) live_neighbors = [i for i in neighbors if i in self._alive] lt = self._life_time if len(neighbors) < 2: lt = self._isolated_life_time if len(live_neighbors) < 3 and ((self._current_time - self._time[address]) / lt) >= 1.0: self._alive.remove(address) self._dying.append(address) self._time[address] = self._current_time self._population -= 1 self.setPixelHLS(address, self._alive_color) # Spread if (self._population < self._population_limit) and random.random() < self._birth_rate * dt: for spread in neighbors: if spread not in (self._growing + self._alive + self._dying + self._fading_out): self._growing.append(spread) self._time[spread] = self._current_time self._population += 1 # Color decay for address in self._dying: p, color = self._get_next_color(address, self._death_time, self._current_time + self.parameter('audio-onset-death-boost').get()) if p >= 1.0: self._dying.remove(address) self._fading_out.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Fade out for address in self._fading_out: p, color = self._get_next_color(address, self._fade_out_time, self._current_time + self.parameter('audio-onset-death-boost').get()) if p >= 1.0: self._fading_out.remove(address) self.setPixelHLS(address, color) # Mass destruction if (self._population == self._population_limit) or \ (self._population > self._mass_destruction_threshold and self._mass_destruction_countdown <= 0): for i in self._alive: if random.random() > 0.95: self._alive.remove(i) self._dying.append(i) self._population -= 1 for i in self._growing: if random.random() > 0.85: self._growing.remove(i) self._dying.append(i) self._population -= 1 self._mass_destruction_countdown = self.parameter('mass-destruction-time').get() def _get_next_color(self, address, time_target, current_time): """ Returns the next color for a pixel, given the pixel's current state """ progress = (current_time - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif current_time == self._time[address]: progress = 0.0 idx = progress / 3.0 if time_target == self._death_time: idx += (1.0 / 3.0) elif time_target == self._fade_out_time: idx += (2.0 / 3.0) return (progress, self._fader.get_color(idx * self._fader_steps))
class StripeGradient(RawPreset): _fader = None def setup(self): self.add_parameter(FloatParameter('speed', 0.01)) self.add_parameter(FloatParameter('angle-speed', 0.1)) self.add_parameter(FloatParameter('stripe-width', 20)) self.add_parameter(FloatParameter('center-orbit-distance', 200)) self.add_parameter(FloatParameter('center-orbit-speed', 0.1)) self.add_parameter(FloatParameter('hue-step', 0.1)) self.add_parameter(IntParameter('posterization', 8)) self.add_parameter(HLSParameter('color-start', (0.0, 0.0, 1.0))) self.add_parameter(HLSParameter('color-end', (1.0, 1.0, 1.0))) self.hue_inner = random.random() + 100 self._center_rotation = random.random() self.stripe_angle = random.random() self.pixels = self.scene().get_all_pixels() cx, cy = self.scene().get_centroid() # Find radius to each pixel self.pixel_distances = {} self.pixel_angles = {} for pixel in self.pixels: x, y = self.scene().get_pixel_location(pixel) dx = x - cx dy = y - cy d = math.sqrt(math.pow(dx, 2) + math.pow(dy, 2)) self.pixel_distances[pixel] = d self.pixel_angles[pixel] = (math.pi + math.atan2(dy, dx)) / (2.0 * math.pi) # Normalize max_distance = max(self.pixel_distances.values()) for pixel in self.pixels: self.pixel_distances[pixel] /= max_distance self.parameter_changed(None) def parameter_changed(self, parameter): fade_colors = [self.parameter('color-start').get(), self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] # fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] # fade_colors = [self.parameter('color-start').get(), self.parameter('color-end').get(), self.parameter('color-start').get()] self._fader = ColorFade(fade_colors, self.parameter('posterization').get()) def reset(self): pass def draw(self, dt): if self._mixer.is_onset(): self.hue_inner = self.hue_inner + self.parameter('hue-step').get() self.hue_inner += dt * self.parameter('speed').get() self._center_rotation += dt * self.parameter('center-orbit-speed').get() self.stripe_angle += dt * self.parameter('angle-speed').get() stripe_width = self.parameter('stripe-width').get() cx, cy = self.scene().get_centroid() cx += math.cos(self._center_rotation) * self.parameter('center-orbit-distance').get() cy += math.sin(self._center_rotation) * self.parameter('center-orbit-distance').get() posterization = self.parameter('posterization').get() for pixel in self.pixels: x, y = self.scene().get_pixel_location(pixel) dx = x - cx dy = y - cy x = dx * math.cos(self.stripe_angle) - dy * math.sin(self.stripe_angle) y = dx * math.sin(self.stripe_angle) + dy * math.cos(self.stripe_angle) x = (x / stripe_width) % 1.0 y = (y / stripe_width) % 1.0 x = abs(x - 0.5) y = abs(y - 0.5) hue = math.floor((x+y) * posterization) / posterization color1 = self._fader.get_color(hue) self.setPixelHLS(pixel, ((color1[0] + self.hue_inner) % 1.0, color1[1], color1[2]))
def _setup_colors(self): self._alive_color = self.parameter('alive-color').get() self._dead_color = self.parameter('dead-color').get() self._black_color = self.parameter('black-color').get() fade_colors = [self._black_color, self._alive_color, self._dead_color, self._black_color] self._fader = ColorFade(fade_colors, tick_rate=self._mixer.get_tick_rate())
def __init__(self, position, fade_colors, fade_steps): self.position = position self.distance = 0 self.color = 0 self._fader = ColorFade(fade_colors, fade_steps) self.alive = True
class Twinkle(RawPreset): """Random pixels fade in and out""" _fading_up = [] _fading_down = [] _time = {} _fader = None _fader_steps = 256 def setup(self): random.seed() self.add_parameter(FloatParameter('birth-rate', 0.15)) self.add_parameter(FloatParameter('fade-up-time', 0.5)) self.add_parameter(FloatParameter('fade-down-time', 4.0)) self.add_parameter(HLSParameter('on-color', (0.1, 1.0, 1.0))) self.add_parameter(HLSParameter('off-color', (1.0, 0.0, 1.0))) self.add_parameter(HLSParameter('beat-color', (1.0, 1.0, 1.0))) self.add_parameter(FloatParameter('beat-births', 25.0)) self.add_parameter(HLSParameter('black-color', (0.0, 0.0, 1.0))) self._setup_colors() self._nbirth = 0 self._current_time = 0 def parameter_changed(self, parameter): self._setup_colors() def _setup_colors(self): self._fader = ColorFade([ self.parameter('black-color').get(), self.parameter('off-color').get(), self.parameter('on-color').get() ], self._fader_steps) def reset(self): self._fading_up = [] self._fading_down = [] self._idle = self.scene().get_all_pixels()[:] self._time = {} def draw(self, dt): self._current_time += dt # Birth if self._mixer.is_onset(): self._nbirth += self.parameter('beat-births').get() self._nbirth += self.parameter('birth-rate').get() * dt for i in range(int(self._nbirth)): if random.random() < self._nbirth: if (len(self._idle) > 0): address = self._idle.pop( random.randint(0, len(self._idle) - 1)) self._fading_up.append(address) self._time[address] = self._current_time self._nbirth -= 1 # Growth for address in self._fading_up: progress = (self._current_time - self._time[address]) / float( self.parameter('fade-up-time').get()) * self._fader_steps color = self._fader.get_color(progress) if progress >= self._fader_steps: self._fading_up.remove(address) self._fading_down.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Decay for address in self._fading_down: progress = (1.0 - (self._current_time - self._time[address]) / float(self.parameter('fade-down-time').get()) ) * self._fader_steps color = self._fader.get_color(progress) if progress <= 0: self._idle.append(address) self._fading_down.remove(address) elif self._mixer.is_onset(): color = self.parameter('beat-color').get() self.setPixelHLS(address, color)
def parameter_changed(self, parameter): self.update_center() fade_colors = ast.literal_eval(self.parameter('color-gradient').get()) self._fader = ColorFade(fade_colors, self._fader_steps)
def parameter_changed(self, parameter): fade_colors = ast.literal_eval(self.parameter('color-gradient').get()) self._fader = ColorFade(fade_colors, self.parameter('posterization').get())
class Twinkle(RawPreset): """Random pixels fade in and out""" _fading_up = [] _fading_down = [] _time = {} _fader = None def setup(self): random.seed() self.add_parameter(FloatParameter('birth-rate', 0.15)) self.add_parameter(FloatParameter('fade-up-time', 0.5)) self.add_parameter(FloatParameter('fade-down-time', 4.0)) self.add_parameter(HLSParameter('on-color', (0.1, 1.0, 1.0))) self.add_parameter(HLSParameter('off-color', (1.0, 0.0, 1.0))) self.add_parameter(HLSParameter('beat-color', (1.0, 1.0, 1.0))) self._setup_colors() self._nbirth = 0; self._current_time = 0; def parameter_changed(self, parameter): if str(parameter) == 'on-color': self._setup_colors() def _setup_colors(self): self._up_target = self.parameter('on-color').get() self._down_target = self.parameter('off-color').get() self._fader = ColorFade([self.parameter('off-color').get(), self.parameter('on-color').get()]) def reset(self): self._fading_up = [] self._fading_down = [] self._idle = self.scene().get_all_pixels()[:] self._time = {} def draw(self, dt): self._current_time += dt # Birth if self._mixer.is_onset(): self._nbirth += 25 self._nbirth += self.parameter('birth-rate').get() for i in range(int(self._nbirth)): if (len(self._idle) > 0) and (random.random() < self._nbirth): address = self._idle.pop(random.randint(0, len(self._idle) - 1)) self._fading_up.append(address) self._time[address] = self._current_time self._nbirth -= 1 # Growth for address in self._fading_up: color = self._get_next_color(address, self._current_time) if color == self._up_target: self._fading_up.remove(address) self._fading_down.append(address) self._time[address] = self._current_time self.setPixelHLS(address, color) # Decay for address in self._fading_down: color = self._get_next_color(address, self._current_time, down=True) if color == self._down_target: self._idle.append(address) self._fading_down.remove(address) if self._mixer.is_onset(): self.setPixelHLS(address, self.parameter('beat-color').get()) else: self.setPixelHLS(address, color) def _get_next_color(self, address, time, down=False): time_target = float(self.parameter('fade-down-time').get()) if down else float(self.parameter('fade-up-time').get()) progress = (time - self._time[address]) / time_target if progress > 1.0: progress = 1.0 elif time == self._time[address]: progress = 0.0 if down: progress = 1.0 - progress return self._fader.get_color(progress)