diff --git a/effects.py b/effects.py index ac478ae..ab69f07 100644 --- a/effects.py +++ b/effects.py @@ -54,3 +54,21 @@ def black(framecount, index, target): target[1] = 0 target[2] = 0 +def adjust_saturation(framecount, index, target, params): + factor = params['factor'] + rgb = sRGBColor(target[0], target[1], target[2], True) + hsv = convert_color(rgb, HSVColor) + hsv.hsv_s = min(hsv.hsv_s*factor,1) + print(params) + print(hsv) + hsv_to_target(hsv, target) + +def rgb(framecount, index, target, params): + r = params["red"] + g = params["green"] + b = params["blue"] + p_index = params["index"] + if index == p_index or p_index == -1: + target[0] = r + target[1] = g + target[2] = b diff --git a/processor.py b/processor.py index 6ae111d..fbf2b1f 100644 --- a/processor.py +++ b/processor.py @@ -6,45 +6,140 @@ from artnet import buildPacket from effects import * import state -AVAILABLE_EFFECTS = [ black, rainbow_whole, rainbow_whole_offset_stat, rainbow_whole_offset_dyn, two_colors_red_blue, two_colors_red_red, two_colors_cyan_blue, two_colors_cyan_orange] +AVAILABLE_EFFECTS = [ + { + "function": black, + "params": None, + }, + { + "function": rainbow_whole, + "params": None, + }, + { + "function": rainbow_whole_offset_stat, + "params": None, + }, + { + "function": rainbow_whole_offset_dyn, + "params": None, + }, + { + "function": two_colors_red_blue, + "params": None, + }, + { + "function": two_colors_red_red, + "params": None + }, + { + "function": two_colors_cyan_blue, + "params": None + }, + { + "function": two_colors_cyan_orange, + "params": None + }, + { + "function": adjust_saturation, + "params": { + "factor": { + "type": "slider", + "min": 0, + "max": 1, + "default": 1, + "step": 0.01 + } + } + }, + { + "function": rgb, + "params": { + "red": { + "type": "slider", + "min": 0, + "max": 255, + "default": 128 + }, + "green": { + "type": "slider", + "min": 0, + "max": 255, + "default": 128 + }, + "blue": { + "type": "slider", + "min": 0, + "max": 255, + "default": 128 + }, + "index": { + "type": "slider", + "min": -1, + "max": 3, + "default": -1 + } + } + } +] -current_effect = rainbow_whole +effect_chain = [ { "function": rainbow_whole, "params": None }, { "function": black, "params": None } ] framecount = 0 def function_str(func): return str(func).split(" ")[1] +def serialize_effect(effect): + return { + "function": function_str(effect["function"]), + "params": effect["params"], + } + +def serialize_chain(chain): + return [ serialize_effect(e) for e in chain ] + def get_options(): return { "effects": { - "available": [ function_str(e) for e in AVAILABLE_EFFECTS ] + "available": [ serialize_effect(e) for e in AVAILABLE_EFFECTS ] } } def serialize_internal_state(): - global current_effect + global effect_chain + return { "chain": serialize_chain(effect_chain) } + +def deserialize_effect(effect_input): + effect = [ x for x in AVAILABLE_EFFECTS if function_str(x["function"]) == effect_input["function"] ][0] + if (effect_input["params"] == {} or effect_input["params"] is None) and effect["params"] is not None: + # assign default params + params = { k: v["default"] for k,v in effect["params"].items() } + else: + params = effect_input["params"] return { - "current_effect": function_str(current_effect) + "function": effect["function"], + "params": params } -def set_immidiate(framecount, channels, update): +def deserialize_chain(chain): + return [ deserialize_effect(effect) for effect in chain ] + +def set_immidiate(framecount, channels, update, params): for inx, (current, target) in enumerate(zip(channels["current"], channels["target"])): - update(framecount, inx, target) + if params is None or params == {}: + update(framecount, inx, target) + else: + update(framecount, inx, target, params) for i in range (0,3): current[i] = target[i] -# TODO make this an acceptor and then mutate async def handle_state_change(old, new): - global current_effect + global effect_chain global framecount - if new["current_effect"] != function_str(current_effect): - new_effect = [ x for x in AVAILABLE_EFFECTS if function_str(x) == new["current_effect"] ][0] - current_effect = new_effect if new_effect != None else current_effect - framecount = 0 + effect_chain = deserialize_chain(new["chain"]) await state.mutate(serialize_internal_state()) async def main(target_ips): - global current_effect + global effect_chain global framecount channels = { "target": [], "current": [] } for x in range(0,4): @@ -61,8 +156,10 @@ async def main(target_ips): while True: old_channels = copy.deepcopy(channels["current"]) - set_immidiate(framecount, channels, current_effect) - if old_channels != channels["current"]: + for effect in effect_chain: + #print("effect: {}".format(effect["function"])) + set_immidiate(framecount, channels, effect["function"], effect["params"]) + if old_channels != channels["current"] or framecount == 0: if debug: print("frame:{} channels:{}".format(framecount, channels)) channels_transmit = channels["current"]