diff --git a/src/config_manager.py b/src/config_manager.py index a5cc4d5..6083004 100644 --- a/src/config_manager.py +++ b/src/config_manager.py @@ -47,6 +47,7 @@ def __init__(self): self.unsave_configs = False self.unsave_mouse_bindings = False self.unsave_keyboard_bindings = False + self.throttle_time = 1.5 self.config = None # Load config @@ -61,6 +62,12 @@ def currentProfilePath(self): App().profilesDirectory, CURRENT_PROFILE_FILENAME) return self._currentProfilePath + def set_throttle_time(self, time): + self.throttle_time = time + + def get_throttle_time(self): + return self.throttle_time + def _get_profiles_directory(self, *name): path = App().profilesDirectory if path.exists(): diff --git a/src/controllers/keybinder.py b/src/controllers/keybinder.py index 5a30dad..0732af9 100644 --- a/src/controllers/keybinder.py +++ b/src/controllers/keybinder.py @@ -24,6 +24,7 @@ class Keybinder(metaclass=Singleton): def __init__(self) -> None: self.delay_count = None self.key_states = None + self.last_act_time = None self.schedule_toggle_off = {} self.schedule_toggle_on = {} self.monitors = None @@ -55,11 +56,13 @@ def init_states(self) -> None: """ # keep states for all registered keys. self.key_states = {} + self.last_act_time = {} self.start_hold_ts = {} for _, v in (ConfigManager().mouse_bindings | ConfigManager().keyboard_bindings).items(): state_name = v[0]+"_"+v[1] self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) self.schedule_toggle_off[state_name] = False self.schedule_toggle_on[state_name] = True self.start_hold_ts[state_name] = math.inf @@ -98,6 +101,8 @@ def get_current_monitor(self) -> int: def meta_action(self, val, action, threshold, is_active: bool) -> None: state_name = "meta_" + action + if self.last_act_time[state_name] > int(time.time() * 1000) - ConfigManager().get_throttle_time() * 1000: + return if action == "pause": if (val > threshold) and (self.key_states[state_name] is False): @@ -110,6 +115,7 @@ def meta_action(self, val, action, threshold, is_active: bool) -> None: self.key_states[state_name] = True elif (val < threshold) and (self.key_states[state_name] is True): self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) if is_active: @@ -127,6 +133,7 @@ def meta_action(self, val, action, threshold, is_active: bool) -> None: elif (val < threshold) and (self.key_states[state_name] is True): self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) elif action == "cycle": if (val > threshold) and (self.key_states[state_name] is @@ -140,15 +147,19 @@ def meta_action(self, val, action, threshold, is_active: bool) -> None: elif (val < threshold) and (self.key_states[state_name] is True): self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) def mouse_action(self, val, action, threshold, mode) -> None: state_name = "mouse_" + action + if self.last_act_time[state_name] > int(time.time() * 1000) - ConfigManager().get_throttle_time() * 1000: + return if mode == Trigger.SINGLE: if val > threshold: if self.key_states[state_name] is False: pydirectinput.click(button=action) self.key_states[state_name] = True + self.last_act_time[state_name] = int(time.time() * 1000) if val < threshold: self.key_states[state_name] = False @@ -160,6 +171,7 @@ def mouse_action(self, val, action, threshold, mode) -> None: elif (val < threshold) and (self.key_states[state_name] is True): pydirectinput.mouseUp(button=action) self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) elif mode == Trigger.DYNAMIC: if val > threshold: @@ -177,11 +189,12 @@ def mouse_action(self, val, action, threshold, mode) -> None: elif (val < threshold) and (self.key_states[state_name] is True): self.key_states[state_name] = False - + self.last_act_time[state_name] = int(time.time() * 1000) if self.holding[state_name]: pydirectinput.mouseUp(button=action) self.holding[state_name] = False self.start_hold_ts[state_name] = math.inf + self.last_act_time[state_name] = int(time.time() * 1000) elif mode == Trigger.TOGGLE: if val > threshold: @@ -194,6 +207,7 @@ def mouse_action(self, val, action, threshold, mode) -> None: if self.schedule_toggle_off[state_name] is True: pydirectinput.mouseUp(button=action) self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) if val < threshold: if self.key_states[state_name] is True: @@ -221,16 +235,20 @@ def mouse_action(self, val, action, threshold, mode) -> None: if self.key_states[state_name] is True: self.key_states[state_name] = False self.start_hold_ts[state_name] = math.inf + self.last_act_time[state_name] = int(time.time() * 1000) def keyboard_action(self, val, keysym, threshold, mode): state_name = "keyboard_" + keysym + if self.last_act_time[state_name] > int(time.time() * 1000) - ConfigManager().get_throttle_time() * 1000: + return if mode == Trigger.SINGLE: if val > threshold: if self.key_states[state_name] is False: pydirectinput.press(keys=keysym) self.key_states[state_name] = True + self.last_act_time[state_name] = int(time.time() * 1000) if val < threshold: self.key_states[state_name] = False @@ -242,6 +260,7 @@ def keyboard_action(self, val, keysym, threshold, mode): elif (val < threshold) and (self.key_states[state_name] is True): pydirectinput.keyUp(key=keysym) self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) elif mode == Trigger.DYNAMIC: if val > threshold: @@ -263,7 +282,8 @@ def keyboard_action(self, val, keysym, threshold, mode): if self.holding[state_name]: pydirectinput.keyUp(key=keysym) self.holding[state_name] = False - self.start_hold_ts[state_name] = math.inf + self.start_hold_ts[state_name] = math.inf + self.last_act_time[state_name] = int(time.time() * 1000) elif mode == Trigger.TOGGLE: if val > threshold: @@ -276,6 +296,7 @@ def keyboard_action(self, val, keysym, threshold, mode): if self.schedule_toggle_off[state_name] is True: pydirectinput.keyUp(key=keysym) self.key_states[state_name] = False + self.last_act_time[state_name] = int(time.time() * 1000) if val < threshold: if self.key_states[state_name] is True: @@ -303,6 +324,7 @@ def keyboard_action(self, val, keysym, threshold, mode): if self.key_states[state_name] is True: self.key_states[state_name] = False self.start_hold_ts[state_name] = math.inf + self.last_act_time[state_name] = int(time.time() * 1000) def act(self, blendshape_values) -> None: """Trigger devices action base on blendshape values diff --git a/src/gui/pages/page_select_gestures.py b/src/gui/pages/page_select_gestures.py index 72c9c4a..27ab305 100644 --- a/src/gui/pages/page_select_gestures.py +++ b/src/gui/pages/page_select_gestures.py @@ -99,8 +99,9 @@ def dialog_callback(self, caller_name, target_gesture): div["volume_bar"].grid() div["tips_label"].grid() div["subtle_label"].grid() - div["timer_slider"].grid() - div["timer_label"].grid() + if 'blink' in target_gesture: + div["timer_slider"].grid() + div["timer_label"].grid() div["trigger_dropdown"].grid() thres_value = div["slider"].get() / 100 trigger = Trigger(div["trigger_dropdown"].get()) diff --git a/src/gui/pages/page_setting.py b/src/gui/pages/page_setting.py index 2eab3b1..5252aac 100644 --- a/src/gui/pages/page_setting.py +++ b/src/gui/pages/page_setting.py @@ -12,6 +12,8 @@ from tkinter import messagebox from src.config_manager import ConfigManager from src.controllers import MouseController +from functools import partial +import tkinter as tk APP_NAME = 'FaceCommander' logger = logging.getLogger("PageSetting") @@ -145,6 +147,43 @@ def __init__(self, master, master_callback:callable, **kwargs): pady=120, sticky="nw") + self.slider = customtkinter.CTkSlider(master=self, + from_=1, + to=300, + width=250, + number_of_steps=300, + command=partial(self.slider_drag_callback)) + self.slider.bind("", + partial(self.slider_mouse_down_callback)) + self.slider.bind("", + partial(self.slider_mouse_up_callback)) + self.slider.grid(row=0, + column=0, + padx=(5, 0), + pady=(160, 10), + sticky="nw") + + self.slider_label = customtkinter.CTkLabel(master=self, + text="0\t Throttle time\t\t 3s", + text_color="#868686", + justify=tk.LEFT) + self.slider_label.cget("font").configure(size=11) + self.slider_label.grid(row=0, + column=0, + padx=(10, 0), + pady=(182, 10), + sticky="nw") + + def slider_drag_callback(self, slider_value: str): + self.slider_dragging = True + + def slider_mouse_down_callback(self, event): + self.slider_dragging = True + + def slider_mouse_up_callback(self, event): + self.slider_dragging = False + ConfigManager().set_throttle_time(self.slider.get()/100) + def open_log_directory(self): log_file_path = App().logPath