working on new shader bank feature

This commit is contained in:
langolierz
2019-12-03 17:31:28 +00:00
parent 9125bf11e1
commit 4313c4b060
9 changed files with 174 additions and 90 deletions

View File

@@ -280,6 +280,9 @@ class Actions(object):
else:
self.message_handler.set_message('INFO', 'no shader loaded')
def toggle_shader_speed(self):
self.shaders.toggle_shader_speed()
def toggle_player_mode(self):
if self.data.player_mode == 'now':
self.data.player_mode = 'next'
@@ -303,6 +306,11 @@ class Actions(object):
self.data.detour_settings['is_playing'] = is_playing
self.video_driver.osc_client.send_message("/detour/is_playing", is_playing)
def toggle_feedback(self):
print('toggle here')
self.data.feedback_active = not self.data.feedback_active
self.video_driver.osc_client.send_message("/toggle_feedback", self.data.feedback_active)
def play_shader_0(self):
self.play_this_shader(0)
@@ -442,17 +450,42 @@ class Actions(object):
def set_the_next_video_alpha_continuous(self, amount):
self.video_driver.next_player.set_alpha_value(amount*255)
def set_the_shader_param_0_continuous(self, amount):
self.shaders.set_param_to_amount(0, amount)
def set_the_shader_param_0_layer_offset_0_continuous(self, amount):
self.shaders.set_param_to_amount(0, amount, layer_offset=0)
def set_the_shader_param_1_continuous(self, amount):
self.shaders.set_param_to_amount(1, amount)
def set_the_shader_param_1_layer_offset_0_continuous(self, amount):
self.shaders.set_param_to_amount(1, amount, layer_offset=0)
def set_the_shader_param_2_continuous(self, amount):
self.shaders.set_param_to_amount(2, amount)
def set_the_shader_param_2_layer_offset_0_continuous(self, amount):
self.shaders.set_param_to_amount(2, amount, layer_offset=0)
def set_the_shader_param_3_layer_offset_0_continuous(self, amount):
self.shaders.set_param_to_amount(3, amount, layer_offset=0)
def set_the_shader_param_0_layer_offset_1_continuous(self, amount):
self.shaders.set_param_to_amount(0, amount, layer_offset=1)
def set_the_shader_param_1_layer_offset_1_continuous(self, amount):
self.shaders.set_param_to_amount(1, amount, layer_offset=1)
def set_the_shader_param_2_layer_offset_1_continuous(self, amount):
self.shaders.set_param_to_amount(2, amount, layer_offset=1)
def set_the_shader_param_3_layer_offset_1_continuous(self, amount):
self.shaders.set_param_to_amount(3, amount, layer_offset=1)
def set_the_shader_param_0_layer_offset_2_continuous(self, amount):
self.shaders.set_param_to_amount(0, amount, layer_offset=2)
def set_the_shader_param_1_layer_offset_2_continuous(self, amount):
self.shaders.set_param_to_amount(1, amount, layer_offset=2)
def set_the_shader_param_2_layer_offset_2_continuous(self, amount):
self.shaders.set_param_to_amount(2, amount, layer_offset=2)
def set_the_shader_param_3_layer_offset_2_continuous(self, amount):
self.shaders.set_param_to_amount(3, amount, layer_offset=2)
def set_the_shader_param_3_continuous(self, amount):
self.shaders.set_param_to_amount(3, amount)
def get_midi_status(self):
self.message_handler.set_message('INFO', 'midi status is {}'.format(self.data.midi_status))
@@ -484,6 +517,10 @@ class Actions(object):
subprocess.call(['tvservice --preferred'], shell=True)
elif self.data.settings['video']['HDMI_MODE']['value'] == 'CEA 4 HDMI':
subprocess.call(['tvservice -e=\"CEA 4 HDMI\"'], shell=True)
elif self.data.settings['video']['HDMI_MODE']['value'] == 'CEA 17 HDMI':
subprocess.call(['tvservice -e=\"CEA 17 HDMI\"'], shell=True)
elif self.data.settings['video']['HDMI_MODE']['value'] == 'CEA 1 HDMI':
subprocess.call(['tvservice -e=\"CEA 1 HDMI\"'], shell=True)
self.refresh_frame_buffer_and_restart_openframeworks()
def check_and_set_output_mode_on_boot(self):

View File

@@ -44,6 +44,7 @@ class Data(object):
self.confirm_action = None
self.player_mode = 'now'
self.feedback_active = False
self.detour_active = False
self.detour_mix_shaders = self.get_list_of_two_input_shaders()
self.detour_settings = collections.OrderedDict([('current_detour',0), ('is_playing', False), ('is_recording', False), ('record_loop', False), ('detour_size', False), ('detour_speed', 0), ('memory_full', False), ('mix_shader', self.detour_mix_shaders[0]), ('detour_position', 5), ('detour_start', 0), ('detour_end', 0), ('detour_mix', 0), ('is_delay', False)])
@@ -52,7 +53,6 @@ class Data(object):
self.current_bankslot = '0-0'
self.shader_layer = 0
self.shader_slots = [None, None, None]
### persisted data (use default if doesnt exits):
self.bank_data = [self.create_empty_bank()]
@@ -360,7 +360,7 @@ class Data(object):
if self.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer' and self.settings['shader']['USE_SHADER']['value'] == 'enabled':
display_modes.append(["SHADERS",'NAV_SHADERS'])
if self.settings['shader']['USE_SHADER_BANK']['value'] == 'enabled' and ["SHADERS",'NAV_SHADERS'] in display_modes:
display_modes.append(["SHADBANK",'PLAY_SHADER'])
display_modes.append(["SHDR_BNK",'PLAY_SHADER'])
if self.settings['detour']['TRY_DEMO']['value'] == 'enabled':
display_modes.append(["FRAMES",'NAV_DETOUR'])
if not with_nav_mode:

View File

@@ -52,7 +52,7 @@ class Display(object):
self.display_text.pack()
def _load_title(self):
if self.data.display_mode == 'SHADERS' or self.data.display_mode == 'SHADBANK':
if self.data.display_mode == 'SHADERS' or self.data.display_mode == 'SHDR_BNK':
self.display_text.insert(END, self.TITLES[1] + ' \n')
self.display_text.tag_add("TITLE", 1.19, 1.31)
elif self.data.display_mode == 'FRAMES':
@@ -88,7 +88,7 @@ class Display(object):
self._load_sampler()
elif self.data.display_mode == 'SHADERS':
self._load_shaders()
elif self.data.display_mode == 'SHADBANK':
elif self.data.display_mode == 'SHDR_BNK':
self._load_shader_bank()
elif self.data.display_mode == 'FRAMES':
self._load_detour()
@@ -170,11 +170,11 @@ class Display(object):
## showing current shader info:
shader = self.shaders.selected_shader_list[self.data.shader_layer]
self.display_text.insert(END, '{:<1}:{:<2} {:<17} '.format \
(self.shaders.selected_status,shader['shad_type'][0], \
shader['name'].lstrip()[0:17] ))
self.display_text.insert(END, '{:<1}lay{:<1}:{:<2} {:<16} '.format \
(self.data.shader_layer,self.shaders.selected_status,shader['shad_type'][0], \
shader['name'].lstrip()[0:16] ))
for i in range(min(4,shader['param_number'])):
display_param = self.format_param_value(self.shaders.selected_param_values[i])
display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i])
if display_param == 100:
display_param == 99
self.display_text.insert(END, 'x{}:{:02d}'.format(i, display_param))
@@ -201,13 +201,13 @@ class Display(object):
self.display_text.insert(END, '{} \n'.format(self.body_title))
self.display_text.insert(END, '{:>6} {:<5} {:<5} '.format(
self.display_text.insert(END, '{:>6} {:<11} {:<5} '.format(
'{}-layer'.format(self.data.shader_layer), 'name', 'type'))
shader = self.shaders.selected_shader_list[self.data.shader_layer]
for i in range(min(4,shader['param_number'])):
display_param = self.format_param_value(self.shaders.selected_param_values[i])
display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i])
if display_param == 100:
display_param == 99
self.display_text.insert(END, 'x{}:{:02d}'.format(i, display_param))
@@ -220,9 +220,12 @@ class Display(object):
self.display_text.tag_add("ZEBRA_STRIPE", self.ROW_OFFSET + index,
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
# highlight the slot of the selected player
current_slot = self.data.shader_slots[self.data.shader_layer]
if current_slot:
self._highlight_this_row(current_slot)
current_slot = self.shaders.selected_shader_list[self.data.shader_layer].get('slot', None)
not_playing_tag = self.shaders.selected_status != ''
if current_slot is not None:
self._highlight_this_row(current_slot, gray=not_playing_tag)
self._highlight_this_param(self.shaders.focused_param)
def _load_detour(self):
@@ -254,13 +257,19 @@ class Display(object):
self.display_text.insert(END, '{:^47} \n'.format('< FUNCTION KEY ON >'))
self.display_text.tag_add('FUNCTION', 16.0,16.0 + self.SELECTOR_WIDTH)
else:
self.display_text.insert(END, '{:8} {:<10} \n'.format('CONTROL:', self.data.control_mode))
feedback = ''
if self.data.feedback_active:
feedback = 'FDBCK'
self.display_text.insert(END, '{:8} {:<28} {:>5} \n'.format('CONTROL:', self.data.control_mode, feedback))
self.display_text.tag_add('TITLE', 16.0,16.0 + self.SELECTOR_WIDTH)
def _highlight_this_row(self, row):
def _highlight_this_row(self, row, gray=False):
highlight_tag = "SELECT"
if gray:
highlight_tag = "BROKEN_PATH"
self.display_text.tag_remove("ZEBRA_STRIPE", self.ROW_OFFSET + row,
self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
self.display_text.tag_add("SELECT", self.ROW_OFFSET + row,
self.display_text.tag_add(highlight_tag, self.ROW_OFFSET + row,
self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
def _unhighlight_this_row(self, row):
@@ -269,7 +278,7 @@ class Display(object):
def _highlight_this_param(self, param_num):
param_row = self.ROW_OFFSET - 1
column_offset = 0.24
column_offset = 0.26
param_length = 0.05
self.display_text.tag_add("SHADER_PARAM", round(param_row + column_offset + param_num*param_length,2),
round(param_row + column_offset + (param_num+1)*param_length, 2))

View File

@@ -1,34 +1,34 @@
{
"0": {
"DEFAULT": ["set_the_shader_param_0_continuous"],
"DEFAULT": ["set_the_shader_param_0_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_mix_continuous"]
},
"1": {
"DEFAULT": ["set_the_shader_param_1_continuous"],
"DEFAULT": ["set_the_shader_param_1_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_speed_position_continuous"]
},
"2": {
"DEFAULT": ["set_the_shader_param_2_continuous"],
"DEFAULT": ["set_the_shader_param_2_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_start_continuous"]
},
"3": {
"DEFAULT": ["set_the_shader_param_3_continuous"],
"DEFAULT": ["set_the_shader_param_3_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_end_continuous"]
},
"4": {
"DEFAULT": ["set_the_shader_param_0_continuous"],
"DEFAULT": ["set_the_shader_param_0_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_mix_continuous"]
},
"5": {
"DEFAULT": ["set_the_shader_param_1_continuous"],
"DEFAULT": ["set_the_shader_param_1_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_speed_position_continuous"]
},
"6": {
"DEFAULT": ["set_the_shader_param_2_continuous"],
"DEFAULT": ["set_the_shader_param_2_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_start_continuous"]
},
"7": {
"DEFAULT": ["set_the_shader_param_3_continuous"],
"DEFAULT": ["set_the_shader_param_3_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_end_continuous"]
}
}

View File

@@ -28,7 +28,8 @@
"LENGTH_SET": ["record_fixed_length"],
"SHADER_PARAM": ["return_to_default_control_mode"],
"CONFIRM": ["perform_confirm_action"],
"NAV_DETOUR": ["toggle_detour_play"]
"NAV_DETOUR": ["toggle_detour_play"],
"PLAY_SHADER": ["toggle_shaders", "toggle_shader_speed"]
},
"d": {
"DEFAULT": ["switch_to_next_player", "toggle_player_mode"],
@@ -57,16 +58,19 @@
"j": {
"DEFAULT": ["load_slot_0_into_next_player","previous_bank"],
"PLAY_SHADER": ["play_shader_0","previous_shader_layer"],
"NAV_SHADERS": ["play_shader_0","previous_shader_layer"],
"NAV_DETOUR": ["switch_to_detour_0", "set_the_detour_mix_0"]
},
"k": {
"DEFAULT": ["load_slot_1_into_next_player","next_bank"],
"PLAY_SHADER": ["play_shader_1","next_shader_layer"],
"NAV_SHADERS": ["play_shader_1","next_shader_layer"],
"NAV_DETOUR": ["switch_to_detour_1", "set_the_detour_mix_1"]
},
"l": {
"DEFAULT": ["load_slot_2_into_next_player","clear_all_slots"],
"PLAY_SHADER": ["play_shader_2","clear_shader_bank"],
"NAV_SHADERS": ["play_shader_2","clear_shader_bank"],
"NAV_DETOUR": ["switch_to_detour_2", "clear_this_detour"]
},
"m": {
@@ -80,7 +84,7 @@
},
"o": {
"DEFAULT": ["load_slot_5_into_next_player","toggle_screen_mirror"],
"PLAY_SHADER": ["play_shader_5"]
"PLAY_SHADER": ["play_shader_5", "toggle_screen_mirror"]
},
"p": {
"DEFAULT": ["load_slot_6_into_next_player","toggle_shaders"],
@@ -91,12 +95,11 @@
"PLAY_SHADER": ["play_shader_7","toggle_detour_mode"]
},
"r": {
"DEFAULT": ["load_slot_8_into_next_player"],
"PLAY_SHADER": ["play_shader_8"]
"DEFAULT": ["load_slot_8_into_next_player", "toggle_feedback"],
"PLAY_SHADER": ["play_shader_8", "toggle_feedback"]
},
"s": {
"DEFAULT": ["load_slot_9_into_next_player","confirm_shutdown"],
"PLAY_SHADER":
["play_shader_9","confirm_shutdown"]
}
"PLAY_SHADER": ["play_shader_9","confirm_shutdown"]
}
}

View File

@@ -1,43 +1,43 @@
{
"control_change 0": {
"DEFAULT": ["set_the_shader_param_0_continuous"],
"DEFAULT": ["set_the_shader_param_0_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_mix_continuous"]
},
"control_change 1": {
"DEFAULT": ["set_the_shader_param_1_continuous"],
"DEFAULT": ["set_the_shader_param_1_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_speed_position_continuous"]
},
"control_change 2": {
"DEFAULT": ["set_the_shader_param_2_continuous"],
"DEFAULT": ["set_the_shader_param_2_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_start_continuous"]
},
"control_change 3": {
"DEFAULT": ["set_the_shader_param_3_continuous"],
"DEFAULT": ["set_the_shader_param_3_layer_offset_0_continuous"],
"NAV_DETOUR": ["set_detour_end_continuous"]
},
"control_change 4": {
"DEFAULT": ["set_the_shader_param_0_continuous"]
"DEFAULT": ["set_the_shader_param_0_layer_offset_1_continuous"]
},
"control_change 5": {
"DEFAULT": ["set_the_shader_param_1_continuous"]
"DEFAULT": ["set_the_shader_param_1_layer_offset_1_continuous"]
},
"control_change 6": {
"DEFAULT": ["set_the_shader_param_2_continuous"]
"DEFAULT": ["set_the_shader_param_2_layer_offset_1_continuous"]
},
"control_change 7": {
"DEFAULT": ["set_the_shader_param_3_continuous"]
"DEFAULT": ["set_the_shader_param_3_layer_offset_1_continuous"]
},
"control_change 8": {
"DEFAULT": ["set_the_shader_param_0_continuous"]
"DEFAULT": ["set_the_shader_param_0_layer_offset_2_continuous"]
},
"control_change 9": {
"DEFAULT": ["set_the_shader_param_1_continuous"]
"DEFAULT": ["set_the_shader_param_1_layer_offset_2_continuous"]
},
"control_change 10": {
"DEFAULT": ["set_the_shader_param_2_continuous"]
"DEFAULT": ["set_the_shader_param_2_layer_offset_2_continuous"]
},
"control_change 11": {
"DEFAULT": ["set_the_shader_param_3_continuous"]
"DEFAULT": ["set_the_shader_param_0_layer_offset_3_continuous"]
},
"note_on 72": {
"NAV_BROWSER": ["move_browser_selection_up"],

View File

@@ -163,7 +163,7 @@
},
"shader": {
"USE_SHADER": {
"action": "update_capture_settings",
"action": null,
"options": [
"enabled",
"disabled"
@@ -171,7 +171,15 @@
"value": "enabled"
},
"USE_SHADER_BANK": {
"action": "update_capture_settings",
"action": null,
"options": [
"enabled",
"disabled"
],
"value": "disabled"
},
"FIX_PARAM_OFFSET_LAYER": {
"action": null,
"options": [
"enabled",
"disabled"
@@ -375,6 +383,7 @@
"options": [
"preferred",
"CEA 4 HDMI",
"CEA 1 HDMI",
"CEA 17 HDMI"
],
"value": "CEA 4 HDMI"

View File

@@ -1,22 +1,25 @@
[
[
{
"name": "wipe.frag",
"name": "add_mix.frag",
"param_number": 4,
"path": "/home/pi/r_e_c_u_r/Shaders/2-input/wipe.frag",
"shad_type": "-"
"path": "/home/pi/r_e_c_u_r/Shaders/2-input/add_mix.frag",
"shad_type": "-",
"slot": 0
},
{
"name": "",
"name": "luma_key.frag",
"param_number": 4,
"path": "",
"shad_type": "-"
"path": "/home/pi/r_e_c_u_r/Shaders/2-input/luma_key.frag",
"shad_type": "-",
"slot": 1
},
{
"name": "",
"name": "blend_add.frag",
"param_number": 4,
"path": "",
"shad_type": "-"
"path": "/home/pi/r_e_c_u_r/Shaders/2-input/blend_add.frag",
"shad_type": "-",
"slot": 2
},
{
"name": "",
@@ -66,13 +69,15 @@
"name": "add_mix.frag",
"param_number": 4,
"path": "/home/pi/r_e_c_u_r/Shaders/2-input/add_mix.frag",
"shad_type": "-"
"shad_type": "-",
"slot": 0
},
{
"name": "",
"name": "hsv_control.frag",
"param_number": 4,
"path": "",
"shad_type": "-"
"path": "/home/pi/r_e_c_u_r/Shaders/1-input/hsv_control.frag",
"shad_type": "-",
"slot": 1
},
{
"name": "",
@@ -125,15 +130,16 @@
],
[
{
"name": "",
"name": "wobble.frag",
"param_number": 4,
"path": "",
"shad_type": "-"
"path": "/home/pi/r_e_c_u_r/Shaders/1-input/wobble.frag",
"shad_type": "-",
"slot": 0
},
{
"name": "",
"name": "rotate.frag",
"param_number": 4,
"path": "",
"path": "/home/pi/r_e_c_u_r/Shaders/1-input/rotate.frag",
"shad_type": "-"
},
{

View File

@@ -12,13 +12,12 @@ class Shaders(object):
self.data = data
self.shaders_menu = menu.ShadersMenu(self.data, self.message_handler, self.MENU_HEIGHT )
self.selected_shader_list = [self.EMPTY_SHADER for i in range(3)]
self.focused_param = None
self.focused_param = 0
self.shaders_menu_list = self.generate_shaders_list()
if self.shaders_menu_list is not None:
pass
self.selected_status = '-' ## going to try using symbols for this : '-' means empty, '▶' means running, '■' means not running, '!' means error
self.selected_param_values = [0.0,0.0,0.0,0.0]
self.selected_param_list = [[0.0,0.0,0.0,0.0] for i in range(3)]
self.selected_speed_list = [1.0, 1.0, 1.0]
#self.load_selected_shader()
def generate_shaders_list(self):
@@ -72,18 +71,18 @@ class Shaders(object):
def load_selected_shader(self):
selected_shader = self.selected_shader_list[self.data.shader_layer]
self.selected_param_values = [0.0,0.0,0.0,0.0]
self.selected_param_list[self.data.shader_layer] = [0.0,0.0,0.0,0.0]
print("select shader: ", selected_shader)
self.osc_client.send_message("/shader/load".format(str(self.data.shader_layer)), [selected_shader['path'],selected_shader['shad_type'] == '2in',selected_shader['param_number']])
self.osc_client.send_message("/shader/{}/load".format(str(self.data.shader_layer)), [selected_shader['path'],selected_shader['shad_type'] == '2in',selected_shader['param_number']])
if not self.selected_status == '':
self.selected_status = ''
def start_selected_shader(self):
self.osc_client.send_message("/shader/start".format(str(self.data.shader_layer)), True)
self.osc_client.send_message("/shader/{}/is_active".format(str(self.data.shader_layer)), True)
self.selected_status = ''
def stop_selected_shader(self):
self.osc_client.send_message("/shader/stop".format(str(self.data.shader_layer)), True)
self.osc_client.send_message("/shader/{}/is_active".format(str(self.data.shader_layer)), False)
self.selected_status = ''
def map_on_shaders_selection(self):
@@ -114,21 +113,32 @@ class Shaders(object):
return is_file, is_selected_shader, selected_shader
def play_this_shader(self, slot):
self.selected_shader_list[self.data.shader_layer] = self.data.shader_bank_data[self.data.shader_layer][slot]
self.load_selected_shader()
print(self.data.shader_bank_data[self.data.shader_layer])
if self.data.shader_bank_data[self.data.shader_layer][slot]['path']:
self.selected_shader_list[self.data.shader_layer] = self.data.shader_bank_data[self.data.shader_layer][slot]
self.selected_shader_list[self.data.shader_layer]['slot'] = slot
self.load_selected_shader()
else:
self.message_handler.set_message('INFO', 'this slot is empty')
def increase_this_param(self, amount_change):
param = self.focused_param
current_amount = self.selected_param_values[param]
current_amount = self.selected_param_list[self.data.shader_layer][param]
amount = self.get_new_param_amount(current_amount,amount_change)
self.set_param_to_amount(param, amount)
def decrease_this_param(self, amount_change):
param = self.focused_param
current_amount = self.selected_param_values[param]
current_amount = self.selected_param_list[self.data.shader_layer][param]
amount = self.get_new_param_amount(current_amount,-amount_change)
self.set_param_to_amount(param, amount)
def toggle_shader_speed(self):
if self.selected_speed_list[self.data.shader_layer] > 0.62:
self.set_speed_to_amount(0.5)
else:
self.set_speed_to_amount(0.75)
@staticmethod
def get_new_param_amount(current, change):
if current + change > 1:
@@ -138,10 +148,20 @@ class Shaders(object):
else:
return current + change
def set_param_to_amount(self, param, amount):
def set_param_to_amount(self, param, amount, layer_offset=0):
start_layer = self.data.shader_layer
if self.data.settings['shader']['FIX_PARAM_OFFSET_LAYER']['value'] == 'enabled':
start_layer = 0
layer = start_layer + layer_offset % 4
if self.data.settings['shader']['X3_AS_SPEED']['value'] == 'enabled' and param == 3:
self.osc_client.send_message("/shader/{}/speed".format(str(self.data.shader_layer)), [param, amount] )
self.set_speed_to_amount(amount, layout_offset=layout_offset)
else:
self.osc_client.send_message("/shader/{}/param".format(str(self.data.shader_layer)), [param, amount] )
self.selected_param_values[param] = amount
self.osc_client.send_message("/shader/{}/param".format(str(layer)), [param, amount] )
self.selected_param_list[layer][param] = amount
def set_speed_to_amount(self, amount, layer_offset=0):
layer = self.data.shader_layer + layer_offset % 4
self.osc_client.send_message("/shader/{}/speed".format(str(layer)), amount )
self.selected_speed_list[layer] = amount