Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -612,6 +612,9 @@ css = """
|
|
| 612 |
.seed-image-upload img { max-height: 120px !important; object-fit: contain; }
|
| 613 |
.main-row { align-items: flex-start !important; }
|
| 614 |
.controls-column { min-width: 280px; }
|
|
|
|
|
|
|
|
|
|
| 615 |
|
| 616 |
/* Mobile responsive styles */
|
| 617 |
@media (max-width: 768px) {
|
|
@@ -635,6 +638,9 @@ def create_app():
|
|
| 635 |
# Latest frame for display
|
| 636 |
latest_frame = gr.State(None)
|
| 637 |
latest_frame_count = gr.State(0)
|
|
|
|
|
|
|
|
|
|
| 638 |
|
| 639 |
gr.Markdown("""
|
| 640 |
# 🌍 Waypoint 1 Small
|
|
@@ -671,15 +677,24 @@ def create_app():
|
|
| 671 |
lines=2,
|
| 672 |
)
|
| 673 |
|
| 674 |
-
with gr.Accordion("
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
)
|
|
|
|
|
|
|
| 681 |
seed_image_upload = gr.Image(
|
| 682 |
-
label="
|
| 683 |
type="pil",
|
| 684 |
sources=["upload", "clipboard"],
|
| 685 |
height=120,
|
|
@@ -690,8 +705,14 @@ def create_app():
|
|
| 690 |
frame_display = gr.Number(label="Frame", value=0, interactive=False)
|
| 691 |
|
| 692 |
# --- Event Handlers ---
|
| 693 |
-
|
| 694 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 695 |
"""Start GPU session - generator that shows loading then first frame."""
|
| 696 |
# Show loading state immediately
|
| 697 |
loading_img = create_loading_image(text="Generating World ...")
|
|
@@ -706,14 +727,15 @@ def create_app():
|
|
| 706 |
)
|
| 707 |
|
| 708 |
# Determine seed image/url
|
|
|
|
| 709 |
seed_image = None
|
| 710 |
seed_url = None
|
| 711 |
|
| 712 |
if uploaded_image is not None:
|
| 713 |
seed_image = uploaded_image
|
| 714 |
-
elif
|
| 715 |
-
|
| 716 |
-
|
| 717 |
|
| 718 |
command_queue = Queue()
|
| 719 |
gen = create_gpu_game_loop(
|
|
@@ -781,22 +803,21 @@ def create_app():
|
|
| 781 |
except StopIteration:
|
| 782 |
return current_frame, current_count, current_frame, current_count
|
| 783 |
|
| 784 |
-
def on_reset(state,
|
| 785 |
"""Reset world with new seed."""
|
| 786 |
if len(state) == 0:
|
| 787 |
return None, 0, None, 0
|
| 788 |
|
| 789 |
gen, command_queue = state
|
| 790 |
|
| 791 |
-
# Priority: uploaded image >
|
| 792 |
seed_image = None
|
| 793 |
seed_url = None
|
| 794 |
|
| 795 |
if uploaded_image is not None:
|
| 796 |
seed_image = uploaded_image
|
| 797 |
-
elif
|
| 798 |
-
|
| 799 |
-
seed_url = SEED_FRAME_URLS[idx]
|
| 800 |
|
| 801 |
command_queue.put(ResetCommand(seed_image=seed_image, seed_url=seed_url, prompt=prompt))
|
| 802 |
|
|
@@ -815,9 +836,15 @@ def create_app():
|
|
| 815 |
return value
|
| 816 |
|
| 817 |
# Wire up events
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 818 |
start_btn.click(
|
| 819 |
fn=on_start,
|
| 820 |
-
inputs=[
|
| 821 |
outputs=[session_state, latest_frame, latest_frame_count,
|
| 822 |
video_output, frame_display, start_btn, stop_btn],
|
| 823 |
)
|
|
@@ -831,7 +858,7 @@ def create_app():
|
|
| 831 |
|
| 832 |
reset_btn.click(
|
| 833 |
fn=on_reset,
|
| 834 |
-
inputs=[session_state,
|
| 835 |
outputs=[latest_frame, latest_frame_count, video_output, frame_display],
|
| 836 |
)
|
| 837 |
|
|
@@ -877,4 +904,4 @@ def main():
|
|
| 877 |
|
| 878 |
|
| 879 |
if __name__ == "__main__":
|
| 880 |
-
main()
|
|
|
|
| 612 |
.seed-image-upload img { max-height: 120px !important; object-fit: contain; }
|
| 613 |
.main-row { align-items: flex-start !important; }
|
| 614 |
.controls-column { min-width: 280px; }
|
| 615 |
+
.world-gallery { margin-bottom: 12px; }
|
| 616 |
+
.world-gallery .gallery { gap: 8px !important; }
|
| 617 |
+
.world-gallery .gallery-item { border-radius: 8px; overflow: hidden; }
|
| 618 |
|
| 619 |
/* Mobile responsive styles */
|
| 620 |
@media (max-width: 768px) {
|
|
|
|
| 638 |
# Latest frame for display
|
| 639 |
latest_frame = gr.State(None)
|
| 640 |
latest_frame_count = gr.State(0)
|
| 641 |
+
|
| 642 |
+
# Selected seed URL from examples
|
| 643 |
+
selected_seed_url = gr.State(None)
|
| 644 |
|
| 645 |
gr.Markdown("""
|
| 646 |
# 🌍 Waypoint 1 Small
|
|
|
|
| 677 |
lines=2,
|
| 678 |
)
|
| 679 |
|
| 680 |
+
with gr.Accordion("World Selection", open=True):
|
| 681 |
+
gr.Markdown("**Choose a starting world** (or leave blank for random):")
|
| 682 |
+
|
| 683 |
+
# Gallery for world selection
|
| 684 |
+
world_gallery = gr.Gallery(
|
| 685 |
+
value=SEED_FRAME_URLS,
|
| 686 |
+
label="Preset Worlds",
|
| 687 |
+
columns=5,
|
| 688 |
+
rows=1,
|
| 689 |
+
height=100,
|
| 690 |
+
object_fit="cover",
|
| 691 |
+
allow_preview=False,
|
| 692 |
+
elem_classes=["world-gallery"],
|
| 693 |
)
|
| 694 |
+
|
| 695 |
+
gr.Markdown("**Or upload your own:**")
|
| 696 |
seed_image_upload = gr.Image(
|
| 697 |
+
label="Custom World Image",
|
| 698 |
type="pil",
|
| 699 |
sources=["upload", "clipboard"],
|
| 700 |
height=120,
|
|
|
|
| 705 |
frame_display = gr.Number(label="Frame", value=0, interactive=False)
|
| 706 |
|
| 707 |
# --- Event Handlers ---
|
| 708 |
+
|
| 709 |
+
def on_gallery_select(evt: gr.SelectData):
|
| 710 |
+
"""Handle gallery selection - return the URL of selected world."""
|
| 711 |
+
if evt.index is not None and evt.index < len(SEED_FRAME_URLS):
|
| 712 |
+
return SEED_FRAME_URLS[evt.index]
|
| 713 |
+
return None
|
| 714 |
+
|
| 715 |
+
def on_start(selected_url, uploaded_image, prompt):
|
| 716 |
"""Start GPU session - generator that shows loading then first frame."""
|
| 717 |
# Show loading state immediately
|
| 718 |
loading_img = create_loading_image(text="Generating World ...")
|
|
|
|
| 727 |
)
|
| 728 |
|
| 729 |
# Determine seed image/url
|
| 730 |
+
# Priority: uploaded image > selected from gallery > random
|
| 731 |
seed_image = None
|
| 732 |
seed_url = None
|
| 733 |
|
| 734 |
if uploaded_image is not None:
|
| 735 |
seed_image = uploaded_image
|
| 736 |
+
elif selected_url is not None:
|
| 737 |
+
seed_url = selected_url
|
| 738 |
+
# else: random will be chosen in create_gpu_game_loop
|
| 739 |
|
| 740 |
command_queue = Queue()
|
| 741 |
gen = create_gpu_game_loop(
|
|
|
|
| 803 |
except StopIteration:
|
| 804 |
return current_frame, current_count, current_frame, current_count
|
| 805 |
|
| 806 |
+
def on_reset(state, selected_url, uploaded_image, prompt):
|
| 807 |
"""Reset world with new seed."""
|
| 808 |
if len(state) == 0:
|
| 809 |
return None, 0, None, 0
|
| 810 |
|
| 811 |
gen, command_queue = state
|
| 812 |
|
| 813 |
+
# Priority: uploaded image > selected from gallery > random
|
| 814 |
seed_image = None
|
| 815 |
seed_url = None
|
| 816 |
|
| 817 |
if uploaded_image is not None:
|
| 818 |
seed_image = uploaded_image
|
| 819 |
+
elif selected_url is not None:
|
| 820 |
+
seed_url = selected_url
|
|
|
|
| 821 |
|
| 822 |
command_queue.put(ResetCommand(seed_image=seed_image, seed_url=seed_url, prompt=prompt))
|
| 823 |
|
|
|
|
| 836 |
return value
|
| 837 |
|
| 838 |
# Wire up events
|
| 839 |
+
world_gallery.select(
|
| 840 |
+
fn=on_gallery_select,
|
| 841 |
+
inputs=[],
|
| 842 |
+
outputs=[selected_seed_url],
|
| 843 |
+
)
|
| 844 |
+
|
| 845 |
start_btn.click(
|
| 846 |
fn=on_start,
|
| 847 |
+
inputs=[selected_seed_url, seed_image_upload, prompt_input],
|
| 848 |
outputs=[session_state, latest_frame, latest_frame_count,
|
| 849 |
video_output, frame_display, start_btn, stop_btn],
|
| 850 |
)
|
|
|
|
| 858 |
|
| 859 |
reset_btn.click(
|
| 860 |
fn=on_reset,
|
| 861 |
+
inputs=[session_state, selected_seed_url, seed_image_upload, current_prompt],
|
| 862 |
outputs=[latest_frame, latest_frame_count, video_output, frame_display],
|
| 863 |
)
|
| 864 |
|
|
|
|
| 904 |
|
| 905 |
|
| 906 |
if __name__ == "__main__":
|
| 907 |
+
main()
|