From fc4cd6353b4dbf12c9aa5a07b86dff3ed11196f4 Mon Sep 17 00:00:00 2001 From: Elektrospy <15101742+Elektrospy@users.noreply.github.com`> Date: Mon, 14 Jan 2019 22:47:57 +0100 Subject: [PATCH] first running version :D added threading added basic byte stream output added fading effect for layers disabled all prints removed asyncio based websocket handling changed websocket library --- main.py => beatsaberceiling.py | 186 +++++++++++++++++---------------- 1 file changed, 98 insertions(+), 88 deletions(-) rename main.py => beatsaberceiling.py (73%) diff --git a/main.py b/beatsaberceiling.py similarity index 73% rename from main.py rename to beatsaberceiling.py index 46169c0..33488ad 100644 --- a/main.py +++ b/beatsaberceiling.py @@ -1,20 +1,38 @@ -#!/usr/bin/env python -# needed for websocket events +#!/usr/bin/env python3 import websocket try: import thread except ImportError: import _thread as thread import threading -import time +from datetime import datetime +import time as time_ import json -# needed for effect layer logic import png import numpy as np -# output import os import sys +# get screen size from parameters +Nx = 80 +try: + Nx = int(sys.argv[1]) +except: + pass + +Ny = 40 +try: + Ny = int(sys.argv[2]) +except: + pass + +# get input parameter +beatsaber_host = '127.0.0.1' +try: + beatsaber_host = int(sys.argv[3]) +except: + pass + class Layer: def __init__(self, new_path): @@ -38,20 +56,45 @@ class Layer: self.layer_current_event_value = 0 self.layer_event_triggered = False self.animation_finished = True - self.animation_update_limit_ms = 25 - self.animation_last_update_ms = int(round(time.time() * 1000)) + self.animation_update_limit_ms = 1 + self.animation_last_update_ms = self.millis() self.animation_current_brightness = self.max_brightness # just debug stuff # print("created layer for " + self.path) def run(self): # print("next frame for " + self.path) + self.run_next_fade_color() self.render_rgb_layer( self.layer_buffer_current_color[0], self.layer_buffer_current_color[1], self.layer_buffer_current_color[2] ) + def millis(self): + dt = datetime.now() + millis = dt.microsecond / 1000 + return int(round((time_.time() * 1000) + int(millis))) + + def run_next_fade_color(self): + if not self.animation_finished and self.animation_current_brightness > 0: + current_millis = self.millis() + if current_millis - self.animation_last_update_ms >= self.animation_update_limit_ms: + # fade rgb values + self.animation_current_brightness -= 10 + self.animation_last_update_ms = self.millis() + + # set current layer color brightness to animation brightness + for i in range(0, 2): + self.layer_buffer_current_color[i] = self.get_new_color_value( + self.layer_buffer_current_color[i], + self.animation_current_brightness + ) + elif self.animation_finished: + # if animation is finished, reset current fade brightness + self.animation_current_brightness = self.max_brightness + # print("animation finished!") + def trigger_event(self, event_value): # print("new event " + self.path + " value: " + str(event_value)) self.layer_event_triggered = True @@ -68,44 +111,31 @@ class Layer: if self.layer_event_triggered: # if event_value == 0: # print("Layer off!") - if 0 > event_value < 3: + if event_value == 1 or event_value == 2: # static blue light output_rgb_array[2] = self.max_brightness + self.animation_finished = True elif event_value == 3: # fade blue light - # reset current brightness of color for new animation - # self.animation_current_brightness = self.max_brightness output_rgb_array[2] = self.max_brightness - elif 4 > event_value < 6: + # reset current brightness of color for new animation + self.animation_current_brightness = self.max_brightness + self.animation_finished = False + # output_rgb_array[2] = self.max_brightness + elif event_value == 5 or event_value == 6: # static red light output_rgb_array[0] = self.max_brightness + self.animation_finished = True elif event_value == 7: # fade red light - # reset current brightness of color for new animation - # self.animation_current_brightness = self.max_brightness output_rgb_array[0] = self.max_brightness + # reset current brightness of color for new animation + self.animation_current_brightness = self.max_brightness + self.animation_finished = False + # output_rgb_array[0] = self.max_brightness # elif event_value != 0 and event_value > 7: # print("unknown event effect value") - # if not self.animation_finished: - # if int(round(time.time() * 1000) / self.animation_last_update_ms) > self.animation_update_limit_ms: - # if event_value == 3: - # # fade blue light - # output_rgb_array[2] = self.get_new_color_value( - # output_rgb_array[2], - # self.animation_current_brightness - # ) - # elif event_value == 7: - # # fade red light - # output_rgb_array[2] = self.get_new_color_value( - # output_rgb_array[0], - # self.animation_current_brightness - # ) - # if self.animation_finished: - # if animation is finished, reset current fade brightness - # self.animation_current_brightness = self.max_brightness - # print("animation finished!") - return output_rgb_array # only used for debbuging @@ -118,8 +148,6 @@ class Layer: # print(output_string) def render_rgb_layer(self, r=0, g=0, b=0): - # for testing - b = self.max_brightness # reset layer buffer, step by number of color values (default 3, rgb) for i in range(0, self.rgb_buffer_length): self.layer_buffer_array[i] = 0 @@ -156,6 +184,14 @@ class Layer: return output_array +# create layer objects for the lights +layer_small = Layer('maps/small.png') +layer_middle = Layer('maps/middle.png') +layer_big = Layer('maps/big.png') +layer_left = Layer('maps/left.png') +layer_right = Layer('maps/right.png') + + # ------------------------------------ # Websocket event part start # ------------------------------------ @@ -215,7 +251,7 @@ def event_beat_map(event_object): def event_beat_map_parse(beatmap_event_object): event_type = beatmap_event_object["type"] event_value = beatmap_event_object["value"] - if 0 < event_type < 5: + if event_type >= 0 and event_type < 5: if event_type == 0: trigger_light_small(event_value) elif event_type == 1: @@ -270,7 +306,7 @@ def on_close(ws): def on_open(ws): def run(*args): while True: - time.sleep(1) + time_.sleep(1) # print("websocket connected") thread.start_new_thread(run, ()) @@ -280,19 +316,20 @@ def on_open(ws): # ------------------------------------ -buffer_length = 80 * 40 * 3 +def get_higher_color_value(value1, value2): + new_value = value2 + if value1 > value2: + new_value = value1 + return new_value -def get_new_color_value(current_value, mapping_value): - mapping_value_float = float(mapping_value / 255) - new_value = current_value * mapping_value_float - return round(new_value) +buffer_length = Nx * Ny * 3 def merge_layer_arrays(layer_first, layer_second): output_array = np.zeros(buffer_length, np.uint8) for idx in range(0, buffer_length): - output_array[idx] = get_new_color_value(layer_first[idx], layer_second[idx]) + output_array[idx] = get_higher_color_value(layer_first[idx], layer_second[idx]) return output_array @@ -306,50 +343,23 @@ def get_merged_layers_array(): return output_array -def loop_layers(): - # print("start layers loop") - time_ms = 10 - t = 0 - # main frame render loop - while True: - t += time_ms / 1000.0 - # layer_small.run() - # layer_middle.run() - # layer_big.run() - # layer_left.run() - # layer_right.run() - # output_buffer = get_merged_layers_array() - # output_bytes = output_buffer.tobytes() +# Start websocket logic thread +ws = websocket.WebSocketApp('ws://' + beatsaber_host + ':6557/socket', + on_message=on_message, + on_error=on_error, + on_close=on_close) +ws.on_open = on_open +wst = threading.Thread(target=ws.run_forever) +wst.daemon = True +wst.start() - layer_middle.run() - layer_middle_frame = layer_middle.get_next_frame() - output_bytes = layer_middle_frame.tobytes() - # print(sys.getsizeof(output_bytes)) - # print("new frame:") - # print(output_bytes) - os.write(1, output_bytes) - - # warte time_ms ms - time.sleep(time_ms * 0.001) - - -if __name__ == '__main__': - layer_small = Layer('maps/small.png') - layer_middle = Layer('maps/middle.png') - layer_big = Layer('maps/big.png') - layer_left = Layer('maps/left.png') - layer_right = Layer('maps/right.png') - - # Start websocket logic thread - # websocket.enableTrace(True) - ws = websocket.WebSocketApp('ws://127.0.0.1:6557/socket', - on_message=on_message, - on_error=on_error, - on_close=on_close) - ws.on_open = on_open - wst = threading.Thread(target=ws.run_forever) - wst.daemon = True - wst.start() - - # Start layer logic thread - loop_layers() +# Start layer logic loop +while True: + layer_small.run() + layer_middle.run() + layer_big.run() + layer_left.run() + layer_right.run() + output_buffer = get_merged_layers_array() + output_bytes = output_buffer.tobytes() + os.write(1, output_bytes)