Skip to content
This repository was archived by the owner on Sep 5, 2025. It is now read-only.

Commit 70d552b

Browse files
committed
roughly implement cursor toggle
1 parent 10c3a10 commit 70d552b

File tree

10 files changed

+131
-35
lines changed

10 files changed

+131
-35
lines changed

configs/default/cursor.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"tick_interval_ms": 16,
1515
"hold_trigger_ms": 500,
1616
"auto_play": false,
17+
"enable": true,
1718
"mouse_acceleration": false,
1819
"use_transformation_matrix": false
1920
}

configs/profile_1/cursor.json

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
{
2-
"fix_width": 640,
3-
"fix_height": 480,
4-
"camera_id": 0,
5-
"tracking_vert_idxs": [
6-
8
7-
],
8-
"spd_up": 40,
9-
"spd_down": 40,
10-
"spd_left": 40,
11-
"spd_right": 40,
12-
"pointer_smooth": 6,
13-
"shape_smooth": 10,
14-
"tick_interval_ms": 16,
15-
"hold_trigger_ms": 500,
16-
"auto_play": false,
17-
"mouse_acceleration": false,
18-
"use_transformation_matrix": false
1+
{
2+
"fix_width": 640,
3+
"fix_height": 480,
4+
"camera_id": 0,
5+
"tracking_vert_idxs": [
6+
8
7+
],
8+
"spd_up": 14,
9+
"spd_down": 12,
10+
"spd_left": 15,
11+
"spd_right": 15,
12+
"pointer_smooth": 6,
13+
"shape_smooth": 10,
14+
"tick_interval_ms": 16,
15+
"hold_trigger_ms": 500,
16+
"auto_play": false,
17+
"enable": true,
18+
"mouse_acceleration": false,
19+
"use_transformation_matrix": false
1920
}
Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,20 @@
1-
{}
1+
{
2+
"Mouth left": [
3+
"mouse",
4+
"cycle",
5+
0.505,
6+
"single"
7+
],
8+
"Mouth right": [
9+
"mouse",
10+
"pause",
11+
0.07930000000000006,
12+
"single"
13+
],
14+
"Open mouth": [
15+
"mouse",
16+
"left",
17+
0.505,
18+
"single"
19+
]
20+
}

configs/profile_2/cursor.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"tick_interval_ms": 16,
1515
"hold_trigger_ms": 500,
1616
"auto_play": false,
17+
"enabled": true,
1718
"mouse_acceleration": false,
1819
"use_transformation_matrix": false
1920
}

src/camera_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
import src.utils as utils
2727
from src.config_manager import ConfigManager
28-
from src.controllers import MouseController
28+
from src.controllers import Keybinder
2929
from src.singleton_meta import Singleton
3030

3131
MAX_SEARCH_CAMS = 5
@@ -123,7 +123,7 @@ def draw_overlay(self, track_loc):
123123
self.frame_buffers["debug"] = self.frame_buffers["raw"].copy()
124124

125125
# Disabled
126-
if not MouseController().is_active.get():
126+
if not Keybinder().is_active.get():
127127
self.frame_buffers["debug"] = add_overlay(
128128
self.frame_buffers["debug"], self.overlay_disabled, 0, 0, 640,
129129
108)

src/controllers/keybinder.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919

2020
import pydirectinput
2121
import win32api
22+
import tkinter as tk
2223

2324
import src.shape_list as shape_list
2425
from src.config_manager import ConfigManager
25-
from src.controllers.mouse_controller import MouseController
2626
from src.singleton_meta import Singleton
2727

2828
logger = logging.getLogger("Keybinder")
@@ -42,6 +42,7 @@ def __init__(self) -> None:
4242
self.holding = False
4343
self.is_started = False
4444
self.last_know_keybinds = {}
45+
self.is_active = None
4546

4647
def start(self):
4748
if not self.is_started:
@@ -51,6 +52,9 @@ def start(self):
5152
self.monitors = self.get_monitors()
5253
self.is_started = True
5354

55+
self.is_active = tk.BooleanVar()
56+
self.is_active.set(ConfigManager().config["auto_play"])
57+
5458
def init_states(self) -> None:
5559
"""Re initializes the state of the keybinder.
5660
If new keybinds are added.
@@ -177,13 +181,14 @@ def act(self, blendshape_values) -> dict:
177181
if mon_id is None:
178182
return
179183

180-
MouseController().toggle_active()
184+
self.toggle_active()
185+
#MouseController().toggle_active()
181186

182187
self.key_states[state_name] = True
183188
elif (val < thres) and (self.key_states[state_name] is True):
184189
self.key_states[state_name] = False
185190

186-
elif MouseController().is_active.get():
191+
elif self.is_active:
187192

188193
if device == "mouse":
189194

@@ -222,6 +227,16 @@ def act(self, blendshape_values) -> dict:
222227
elif device == "keyboard":
223228
self.keyboard_action(val, action, thres, mode)
224229

230+
def set_active(self, flag: bool) -> None:
231+
self.is_active.set(flag)
232+
if flag:
233+
self.delay_count = 0
234+
235+
def toggle_active(self):
236+
logging.info("Toggle active")
237+
curr_state = self.is_active.get()
238+
self.set_active(not curr_state)
239+
225240
def destroy(self):
226241
"""Destroy the keybinder"""
227242
return

src/controllers/mouse_controller.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ def __init__(self):
4848
self.is_started = False
4949
self.is_destroyed = False
5050
self.stop_flag = None
51-
self.is_active = None
51+
self.is_active = tk.BooleanVar()
52+
self.is_enabled = None
5253

5354
def start(self):
5455
if not self.is_started:
@@ -60,8 +61,8 @@ def start(self):
6061
self.screen_w, self.screen_h = pyautogui.size()
6162
self.calc_smooth_kernel()
6263

63-
self.is_active = tk.BooleanVar()
64-
self.is_active.set(ConfigManager().config["auto_play"])
64+
self.is_enabled = tk.BooleanVar()
65+
self.is_enabled.set(ConfigManager().config["enable"])
6566

6667
self.stop_flag = threading.Event()
6768
self.pool.submit(self.main_loop)
@@ -102,7 +103,7 @@ def main_loop(self) -> None:
102103
return
103104

104105
while not self.stop_flag.is_set():
105-
if not self.is_active.get():
106+
if not self.is_active.get() or not self.is_enabled.get():
106107
time.sleep(0.001)
107108
continue
108109

@@ -136,6 +137,11 @@ def main_loop(self) -> None:
136137

137138
time.sleep(ConfigManager().config["tick_interval_ms"] / 1000)
138139

140+
def set_enabled(self, flag: bool) -> None:
141+
self.is_enabled.set(flag)
142+
if flag:
143+
self.delay_count = 0
144+
139145
def set_active(self, flag: bool) -> None:
140146
self.is_active.set(flag)
141147
if flag:

src/gui/frames/frame_cam_preview.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from src.camera_manager import CameraManager
2121
from src.config_manager import ConfigManager
22-
from src.controllers import MouseController
22+
from src.controllers import Keybinder
2323
from src.gui.frames.safe_disposable_frame import SafeDisposableFrame
2424

2525
CANVAS_WIDTH = 216
@@ -72,7 +72,7 @@ def __init__(self, master, master_callback: callable, **kwargs):
7272
border_color="transparent",
7373
switch_height=18,
7474
switch_width=32,
75-
variable=MouseController().is_active,
75+
variable=Keybinder().is_active,
7676
command=lambda: master_callback(
7777
"toggle_switch", {"switch_status": self.toggle_switch.get()}),
7878
onvalue=1,
@@ -87,7 +87,7 @@ def __init__(self, master, master_callback: callable, **kwargs):
8787
pady=5,
8888
sticky="nw")
8989

90-
# Toggle label
90+
# Toggle description label
9191
self.toggle_label = customtkinter.CTkLabel(
9292
master=self,
9393
compound='right',

src/gui/main_gui.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import src.gui.frames as frames
2222
import src.gui.pages as pages
2323
from src.config_manager import ConfigManager
24-
from src.controllers import MouseController
24+
from src.controllers import Keybinder, MouseController
2525

2626
customtkinter.set_appearance_mode("light")
2727
customtkinter.set_default_color_theme("assets/themes/google_theme.json")
@@ -162,10 +162,13 @@ def cam_preview_callback(self, command, args: dict):
162162
if command == "toggle_switch":
163163
self.set_mediapipe_mouse_enable(new_state=args["switch_status"])
164164

165+
165166
def set_mediapipe_mouse_enable(self, new_state: bool):
166167
if new_state:
168+
Keybinder().set_active(True)
167169
MouseController().set_active(True)
168170
else:
171+
Keybinder().set_active(False)
169172
MouseController().set_active(False)
170173

171174
def change_page(self, target_page_name: str):

src/gui/pages/page_cursor.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from PIL import Image
2222

2323
from src.config_manager import ConfigManager
24-
from src.controllers import MouseController
24+
from src.controllers import MouseController, Keybinder
2525
from src.gui.balloon import Balloon
2626
from src.gui.frames.safe_disposable_frame import SafeDisposableFrame
2727

@@ -73,6 +73,44 @@ def __init__(
7373
})
7474

7575
self.load_initial_config()
76+
# Toggle label
77+
self.toggle_label = customtkinter.CTkLabel(master=self,
78+
compound='right',
79+
text="Face control",
80+
text_color="black",
81+
justify=tkinter.RIGHT)
82+
self.toggle_label.cget("font").configure(size=14)
83+
self.toggle_label.grid(row=2,
84+
column=0,
85+
padx=(10, 0),
86+
pady=5,
87+
sticky="nw")
88+
89+
90+
# Toggle switch
91+
self.toggle_switch = customtkinter.CTkSwitch(
92+
master=self,
93+
text="",
94+
width=200,
95+
border_color="transparent",
96+
switch_height=18,
97+
switch_width=32,
98+
command=lambda: self.cursor_toggle_callback(
99+
"toggle_switch", {"switch_status": self.toggle_switch.get()}),
100+
variable=MouseController().is_enabled,
101+
onvalue=1,
102+
offvalue=0,
103+
)
104+
if ConfigManager().config["auto_play"]:
105+
self.toggle_switch.select()
106+
107+
self.toggle_switch.grid(row=2,
108+
column=1,
109+
padx=(100, 0),
110+
pady=5,
111+
sticky="nw")
112+
113+
76114

77115
def load_initial_config(self):
78116
"""Load default from config and set the UI
@@ -218,6 +256,18 @@ def slider_mouse_up_callback(self, div_name: str, event):
218256
def inner_refresh_profile(self):
219257
self.load_initial_config()
220258

259+
def cursor_toggle_callback(self, command, args: dict):
260+
logger.info(f"cursor_toggle_callback {command} with {args}")
261+
262+
if command == "toggle_switch":
263+
self.set_mediapipe_mouse_enable(new_state=args["switch_status"])
264+
265+
def set_mediapipe_mouse_enable(self, new_state: bool):
266+
if new_state:
267+
MouseController().set_enabled(True)
268+
else:
269+
MouseController().set_enabled(False)
270+
221271

222272
class PageCursor(SafeDisposableFrame):
223273

@@ -241,7 +291,7 @@ def __init__(self, master, **kwargs):
241291
columnspan=1)
242292

243293
# Description.
244-
des_txt = "Mouse cursor moves with your head movement. Use this settings to adjust how fast your mouse moves in each direction."
294+
des_txt = "Adjust how the mouse cursor responds to your head movements."
245295
des_label = customtkinter.CTkLabel(master=self,
246296
text=des_txt,
247297
wraplength=300,
@@ -251,7 +301,7 @@ def __init__(self, master, **kwargs):
251301

252302
# Inner frame
253303
self.inner_frame = FrameSelectGesture(self)
254-
self.inner_frame.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
304+
self.inner_frame.grid(row=4, column=0, padx=5, pady=5, sticky="nw")
255305

256306
def refresh_profile(self):
257307
self.inner_frame.inner_refresh_profile()

0 commit comments

Comments
 (0)