Fix reliable spacebar play/pause toggle
Browse files- kimodo/demo/ui.py +26 -64
kimodo/demo/ui.py
CHANGED
|
@@ -5,6 +5,7 @@
|
|
| 5 |
import math
|
| 6 |
import os
|
| 7 |
import threading
|
|
|
|
| 8 |
from typing import Optional
|
| 9 |
|
| 10 |
from kimodo.constraints import load_constraints_lst, save_constraints_lst
|
|
@@ -289,19 +290,15 @@ def create_gui(
|
|
| 289 |
examples_base_dir = demo.get_examples_base_dir(model_name, absolute=True)
|
| 290 |
example_dict = viser_utils.load_example_cases(examples_base_dir)
|
| 291 |
example_names = list(example_dict.keys())
|
| 292 |
-
|
| 293 |
-
"[kimodo][examples][init]"
|
| 294 |
-
f" client={client_id} model={model_name} base={examples_base_dir}"
|
| 295 |
-
f" disk_count={len(example_dict)} has_09={QWEN_EXAMPLE_NAME in example_names}"
|
| 296 |
-
f" tail={example_names[-3:] if len(example_names) >= 3 else example_names}"
|
| 297 |
-
)
|
| 298 |
gui_examples_dropdown = client.gui.add_dropdown(
|
| 299 |
"Example",
|
| 300 |
options=example_names,
|
|
|
|
| 301 |
)
|
| 302 |
gui_load_example_button = client.gui.add_button(
|
| 303 |
"Load Example",
|
| 304 |
-
hint="Load the selected example.",
|
| 305 |
disabled=False,
|
| 306 |
)
|
| 307 |
|
|
@@ -309,21 +306,15 @@ def create_gui(
|
|
| 309 |
new_example_dict: dict[str, str],
|
| 310 |
keep_selection: bool = True,
|
| 311 |
) -> None:
|
| 312 |
-
print(
|
| 313 |
-
"[kimodo][examples][update][entry]"
|
| 314 |
-
f" client={client_id} model={model_name} keep_selection={keep_selection}"
|
| 315 |
-
f" incoming_count={len(new_example_dict)} current_value={gui_examples_dropdown.value}"
|
| 316 |
-
)
|
| 317 |
example_names_local = list(new_example_dict.keys())
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
gui_examples_dropdown.options = example_names_local
|
| 319 |
-
print(
|
| 320 |
-
"[kimodo][examples][update][exit]"
|
| 321 |
-
f" client={client_id} model={model_name} count={len(example_names_local)}"
|
| 322 |
-
f" has_09={QWEN_EXAMPLE_NAME in example_names_local}"
|
| 323 |
-
f" tail={example_names_local[-3:] if len(example_names_local) >= 3 else example_names_local}"
|
| 324 |
-
)
|
| 325 |
if keep_selection and gui_examples_dropdown.value in example_names_local:
|
| 326 |
return
|
|
|
|
| 327 |
|
| 328 |
with client.gui.add_folder("Generate", expand_by_default=True):
|
| 329 |
gui_duration = client.gui.add_markdown(content=f"Total duration: {DEFAULT_CUR_DURATION:.1f} (sec)")
|
|
@@ -386,7 +377,7 @@ def create_gui(
|
|
| 386 |
min=2,
|
| 387 |
max=1000,
|
| 388 |
step=10,
|
| 389 |
-
initial_value=
|
| 390 |
)
|
| 391 |
with client.gui.add_folder("Classifier-Free Guidance", expand_by_default=False):
|
| 392 |
gui_cfg_checkbox = client.gui.add_checkbox(
|
|
@@ -2279,28 +2270,11 @@ def create_gui(
|
|
| 2279 |
if session is None:
|
| 2280 |
return
|
| 2281 |
|
| 2282 |
-
|
| 2283 |
-
print(
|
| 2284 |
-
"[kimodo][examples][load_click][entry]"
|
| 2285 |
-
f" client={client_id} selected={selected_example}"
|
| 2286 |
-
f" has_09={QWEN_EXAMPLE_NAME in list(gui_examples_dropdown.options)}"
|
| 2287 |
-
f" options_count={len(list(gui_examples_dropdown.options))}"
|
| 2288 |
-
)
|
| 2289 |
-
|
| 2290 |
-
if selected_example in (QWEN_EXAMPLE_NAME, QWEN_EXAMPLE_LEGACY_NAME):
|
| 2291 |
-
print(
|
| 2292 |
-
"[kimodo][examples][load_click][qwen]"
|
| 2293 |
-
f" client={client_id} selected={selected_example}"
|
| 2294 |
-
)
|
| 2295 |
load_qwen_example_plan(event_client)
|
| 2296 |
return
|
| 2297 |
|
| 2298 |
-
if not session.example_dict or (
|
| 2299 |
-
print(
|
| 2300 |
-
"[kimodo][examples][load_click][missing]"
|
| 2301 |
-
f" client={client_id} selected={selected_example}"
|
| 2302 |
-
f" session_examples={len(session.example_dict) if session.example_dict else 0}"
|
| 2303 |
-
)
|
| 2304 |
event_client.add_notification(
|
| 2305 |
title="No examples available",
|
| 2306 |
body="No examples found for the selected model.",
|
|
@@ -2309,11 +2283,7 @@ def create_gui(
|
|
| 2309 |
)
|
| 2310 |
return
|
| 2311 |
|
| 2312 |
-
example_path = session.example_dict[
|
| 2313 |
-
print(
|
| 2314 |
-
"[kimodo][examples][load_click][exit]"
|
| 2315 |
-
f" client={client_id} selected={selected_example} path={example_path}"
|
| 2316 |
-
)
|
| 2317 |
load_example_from_path(event_client, example_path, gui_load_gt_checkbox.value)
|
| 2318 |
|
| 2319 |
@gui_load_example_from_path_button.on_click
|
|
@@ -3155,18 +3125,16 @@ def create_gui(
|
|
| 3155 |
gui_save_example_button.disabled = False
|
| 3156 |
gui_save_motion_button.disabled = False
|
| 3157 |
gui_download_button.disabled = False
|
| 3158 |
-
|
| 3159 |
-
|
| 3160 |
-
|
| 3161 |
-
|
| 3162 |
-
|
| 3163 |
-
|
| 3164 |
-
|
| 3165 |
-
|
| 3166 |
-
|
| 3167 |
-
|
| 3168 |
-
pass
|
| 3169 |
-
|
| 3170 |
demo.check_cuda_health()
|
| 3171 |
|
| 3172 |
#
|
|
@@ -3397,8 +3365,6 @@ def create_gui(
|
|
| 3397 |
#
|
| 3398 |
# Keyboard events
|
| 3399 |
#
|
| 3400 |
-
space_pressed = [False]
|
| 3401 |
-
|
| 3402 |
@client.scene.on_keyboard_event("keydown", debounce_ms=100)
|
| 3403 |
def handle_key(event: viser.KeyboardEvent) -> None:
|
| 3404 |
# Check if client session still exists
|
|
@@ -3407,15 +3373,11 @@ def create_gui(
|
|
| 3407 |
|
| 3408 |
session = demo.client_sessions[client_id]
|
| 3409 |
|
| 3410 |
-
if event.event_type == "keyup":
|
| 3411 |
-
if event.key == " ":
|
| 3412 |
-
space_pressed[0] = False
|
| 3413 |
-
return
|
| 3414 |
-
|
| 3415 |
# Space bar: only toggle on FIRST press
|
| 3416 |
if event.key == " ":
|
| 3417 |
-
|
| 3418 |
-
|
|
|
|
| 3419 |
play_pause_button_callback(session)
|
| 3420 |
return
|
| 3421 |
|
|
|
|
| 5 |
import math
|
| 6 |
import os
|
| 7 |
import threading
|
| 8 |
+
import time
|
| 9 |
from typing import Optional
|
| 10 |
|
| 11 |
from kimodo.constraints import load_constraints_lst, save_constraints_lst
|
|
|
|
| 290 |
examples_base_dir = demo.get_examples_base_dir(model_name, absolute=True)
|
| 291 |
example_dict = viser_utils.load_example_cases(examples_base_dir)
|
| 292 |
example_names = list(example_dict.keys())
|
| 293 |
+
example_names.append(QWEN_EXAMPLE_NAME)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
gui_examples_dropdown = client.gui.add_dropdown(
|
| 295 |
"Example",
|
| 296 |
options=example_names,
|
| 297 |
+
initial_value=example_names[0],
|
| 298 |
)
|
| 299 |
gui_load_example_button = client.gui.add_button(
|
| 300 |
"Load Example",
|
| 301 |
+
hint="Load the selected example (or Qwen agentic prompt plan).",
|
| 302 |
disabled=False,
|
| 303 |
)
|
| 304 |
|
|
|
|
| 306 |
new_example_dict: dict[str, str],
|
| 307 |
keep_selection: bool = True,
|
| 308 |
) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
example_names_local = list(new_example_dict.keys())
|
| 310 |
+
if QWEN_EXAMPLE_NAME not in example_names_local:
|
| 311 |
+
example_names_local.append(QWEN_EXAMPLE_NAME)
|
| 312 |
+
if QWEN_EXAMPLE_LEGACY_NAME not in example_names_local:
|
| 313 |
+
example_names_local.append(QWEN_EXAMPLE_LEGACY_NAME)
|
| 314 |
gui_examples_dropdown.options = example_names_local
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
if keep_selection and gui_examples_dropdown.value in example_names_local:
|
| 316 |
return
|
| 317 |
+
gui_examples_dropdown.value = example_names_local[0]
|
| 318 |
|
| 319 |
with client.gui.add_folder("Generate", expand_by_default=True):
|
| 320 |
gui_duration = client.gui.add_markdown(content=f"Total duration: {DEFAULT_CUR_DURATION:.1f} (sec)")
|
|
|
|
| 377 |
min=2,
|
| 378 |
max=1000,
|
| 379 |
step=10,
|
| 380 |
+
initial_value=100,
|
| 381 |
)
|
| 382 |
with client.gui.add_folder("Classifier-Free Guidance", expand_by_default=False):
|
| 383 |
gui_cfg_checkbox = client.gui.add_checkbox(
|
|
|
|
| 2270 |
if session is None:
|
| 2271 |
return
|
| 2272 |
|
| 2273 |
+
if gui_examples_dropdown.value in (QWEN_EXAMPLE_NAME, QWEN_EXAMPLE_LEGACY_NAME):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2274 |
load_qwen_example_plan(event_client)
|
| 2275 |
return
|
| 2276 |
|
| 2277 |
+
if not session.example_dict or (gui_examples_dropdown.value not in session.example_dict):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2278 |
event_client.add_notification(
|
| 2279 |
title="No examples available",
|
| 2280 |
body="No examples found for the selected model.",
|
|
|
|
| 2283 |
)
|
| 2284 |
return
|
| 2285 |
|
| 2286 |
+
example_path = session.example_dict[gui_examples_dropdown.value]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2287 |
load_example_from_path(event_client, example_path, gui_load_gt_checkbox.value)
|
| 2288 |
|
| 2289 |
@gui_load_example_from_path_button.on_click
|
|
|
|
| 3125 |
gui_save_example_button.disabled = False
|
| 3126 |
gui_save_motion_button.disabled = False
|
| 3127 |
gui_download_button.disabled = False
|
| 3128 |
+
# Reuse persistent notification instead of creating a new one
|
| 3129 |
+
try:
|
| 3130 |
+
generating_notif.title = "Generation failed!"
|
| 3131 |
+
generating_notif.body = f"Error: {str(e)}"
|
| 3132 |
+
generating_notif.loading = False
|
| 3133 |
+
generating_notif.with_close_button = True
|
| 3134 |
+
generating_notif.auto_close_seconds = 6.0
|
| 3135 |
+
generating_notif.color = "red"
|
| 3136 |
+
except Exception:
|
| 3137 |
+
pass
|
|
|
|
|
|
|
| 3138 |
demo.check_cuda_health()
|
| 3139 |
|
| 3140 |
#
|
|
|
|
| 3365 |
#
|
| 3366 |
# Keyboard events
|
| 3367 |
#
|
|
|
|
|
|
|
| 3368 |
@client.scene.on_keyboard_event("keydown", debounce_ms=100)
|
| 3369 |
def handle_key(event: viser.KeyboardEvent) -> None:
|
| 3370 |
# Check if client session still exists
|
|
|
|
| 3373 |
|
| 3374 |
session = demo.client_sessions[client_id]
|
| 3375 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3376 |
# Space bar: only toggle on FIRST press
|
| 3377 |
if event.key == " ":
|
| 3378 |
+
now = time.monotonic()
|
| 3379 |
+
if now - session.last_space_toggle_time >= 0.2:
|
| 3380 |
+
session.last_space_toggle_time = now
|
| 3381 |
play_pause_button_callback(session)
|
| 3382 |
return
|
| 3383 |
|