import kivy from kivy.uix.screenmanager import Screen import os import json import math from kivy.clock import Clock from kivy.properties import StringProperty, NumericProperty, AliasProperty from py_scripts.utils import ( process_preview_util, optimize_route_entries_util ) from py_scripts.video_3d_generator import generate_3d_video_animation from kivy.uix.popup import Popup from kivy.uix.button import Button from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.uix.progressbar import ProgressBar from kivy.uix.textinput import TextInput from config import RESOURCES_FOLDER class CreateAnimationScreen(Screen): project_name = StringProperty("") preview_html_path = StringProperty("") # Path to the HTML file for preview preview_image_path = StringProperty("") # Add this line preview_image_version = NumericProperty(0) # Add this line def get_preview_image_source(self): project_folder = os.path.join(RESOURCES_FOLDER, "projects", self.project_name) img_path = os.path.join(project_folder, "preview.png") if os.path.exists(img_path): return img_path return "resources/images/track.png" preview_image_source = AliasProperty( get_preview_image_source, None, bind=['project_name', 'preview_image_version'] ) def on_pre_enter(self): # Update the route entries label with the actual number of entries project_folder = os.path.join(RESOURCES_FOLDER, "projects", self.project_name) positions_path = os.path.join(project_folder, "positions.json") count = 0 if os.path.exists(positions_path): with open(positions_path, "r") as f: try: positions = json.load(f) count = len(positions) except Exception: count = 0 self.ids.route_entries_label.text = f"Your route has {count} entries," def open_rename_popup(self): from kivy.uix.popup import Popup from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.textinput import TextInput from kivy.uix.label import Label layout = BoxLayout(orientation='vertical', spacing=10, padding=10) label = Label(text="Enter new project name:") input_field = TextInput(text=self.project_name, multiline=False) btn_save = Button(text="Save", background_color=(0.008, 0.525, 0.290, 1)) btn_cancel = Button(text="Cancel") layout.add_widget(label) layout.add_widget(input_field) layout.add_widget(btn_save) layout.add_widget(btn_cancel) popup = Popup( title="Rename Project", content=layout, size_hint=(0.92, None), size=(0, 260), auto_dismiss=False ) def do_rename(instance): new_name = input_field.text.strip() if new_name and new_name != self.project_name: if self.rename_project_folder(self.project_name, new_name): self.project_name = new_name popup.dismiss() self.on_pre_enter() # Refresh label else: label.text = "Rename failed (name exists?)" else: label.text = "Please enter a new name." btn_save.bind(on_press=do_rename) btn_cancel.bind(on_press=lambda x: popup.dismiss()) popup.open() def rename_project_folder(self, old_name, new_name): import os old_path = os.path.join(RESOURCES_FOLDER, "projects", old_name) new_path = os.path.join(RESOURCES_FOLDER, "projects", new_name) if os.path.exists(old_path) and not os.path.exists(new_path): os.rename(old_path, new_path) return True return False def optimize_route_entries(self): # Create the popup and UI elements layout = BoxLayout(orientation='vertical', spacing=10, padding=10) label = Label(text="Processing route entries...") progress = ProgressBar(max=100, value=0) layout.add_widget(label) layout.add_widget(progress) popup = Popup( title="Optimizing Route", content=layout, size_hint=(0.92, None), size=(0, 260), auto_dismiss=False ) popup.open() # Now call the utility function with these objects optimize_route_entries_util( self.project_name, RESOURCES_FOLDER, label, progress, popup, Clock, on_save=lambda: self.on_pre_enter() ) def preview_route(self): # Show processing popup layout = BoxLayout(orientation='vertical', spacing=10, padding=10) label = Label(text="Processing route preview...") progress = ProgressBar(max=100, value=0) layout.add_widget(label) layout.add_widget(progress) popup = Popup( title="Previewing Route", content=layout, size_hint=(0.8, None), size=(0, 180), auto_dismiss=False ) popup.open() def set_preview_image_path(path): self.preview_image_path = path self.preview_image_version += 1 # Force AliasProperty to update self.property('preview_image_source').dispatch(self) self.ids.preview_image.reload() # Schedule the processing function Clock.schedule_once( lambda dt: process_preview_util( self.project_name, RESOURCES_FOLDER, label, progress, popup, self.ids.preview_image, set_preview_image_path, Clock ), 0.5 ) def open_pauses_popup(self): """Navigate to the pause edit screen""" pause_edit_screen = self.manager.get_screen("pause_edit") pause_edit_screen.set_project_and_callback(self.project_name, self.on_pre_enter) self.manager.current = "pause_edit" def generate_3d_video(self): """Show video generation mode selection popup""" self.show_video_generation_options() def generate_3d_video_test_mode(self): """Generate a 3D video animation in 720p test mode for faster processing""" # Show processing popup with test mode indication layout = BoxLayout(orientation='vertical', spacing=10, padding=10) label = Label(text="Preparing 720p test video generation...") progress = ProgressBar(max=100, value=0) layout.add_widget(label) layout.add_widget(progress) popup = Popup( title="Generating 3D Video Animation (720p Test Mode)", content=layout, size_hint=(0.9, None), size=(0, 200), auto_dismiss=False ) popup.open() # Schedule the 3D video generation in test mode Clock.schedule_once( lambda dt: generate_3d_video_animation( self.project_name, RESOURCES_FOLDER, label, progress, popup, Clock, test_mode=True # Enable test mode ), 0.5 ) def generate_3d_video_production_mode(self): """Generate a 3D video animation in 2K production mode for high quality""" # Show processing popup with production mode indication layout = BoxLayout(orientation='vertical', spacing=10, padding=10) label = Label(text="Preparing 2K production video generation...") progress = ProgressBar(max=100, value=0) layout.add_widget(label) layout.add_widget(progress) popup = Popup( title="Generating 3D Video Animation (2K Production Mode)", content=layout, size_hint=(0.9, None), size=(0, 200), auto_dismiss=False ) popup.open() # Schedule the 3D video generation in production mode Clock.schedule_once( lambda dt: generate_3d_video_animation( self.project_name, RESOURCES_FOLDER, label, progress, popup, Clock, test_mode=False # Disable test mode for production ), 0.5 ) def show_video_generation_options(self): """Show popup with video generation mode options""" from kivy.uix.popup import Popup from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.label import Label layout = BoxLayout(orientation='vertical', spacing=15, padding=15) # Title title_label = Label( text="Choose Video Generation Mode", font_size=18, size_hint_y=None, height=40, color=(1, 1, 1, 1) ) layout.add_widget(title_label) # Test mode description test_layout = BoxLayout(orientation='vertical', spacing=5) test_title = Label( text="🏃‍♂️ 720p Test Mode (Fast)", font_size=16, size_hint_y=None, height=30, color=(0.2, 0.8, 0.2, 1) ) test_desc = Label( text="• Resolution: 1280x720\n• Frame rate: 30 FPS\n• ~3x faster generation\n• Perfect for quick previews", font_size=12, size_hint_y=None, height=80, color=(0.9, 0.9, 0.9, 1), halign="left", valign="middle" ) test_desc.text_size = (None, None) test_layout.add_widget(test_title) test_layout.add_widget(test_desc) layout.add_widget(test_layout) # Test mode button test_btn = Button( text="Generate 720p Test Video", background_color=(0.2, 0.8, 0.2, 1), size_hint_y=None, height=50, font_size=14 ) layout.add_widget(test_btn) # Production mode description prod_layout = BoxLayout(orientation='vertical', spacing=5) prod_title = Label( text="🎯 2K Production Mode (High Quality)", font_size=16, size_hint_y=None, height=30, color=(0.8, 0.2, 0.2, 1) ) prod_desc = Label( text="• Resolution: 2560x1440\n• Frame rate: 60 FPS\n• Cinema-quality results\n• Ultra-detailed visuals", font_size=12, size_hint_y=None, height=80, color=(0.9, 0.9, 0.9, 1), halign="left", valign="middle" ) prod_desc.text_size = (None, None) prod_layout.add_widget(prod_title) prod_layout.add_widget(prod_desc) layout.add_widget(prod_layout) # Production mode button prod_btn = Button( text="Generate 2K Production Video", background_color=(0.8, 0.2, 0.2, 1), size_hint_y=None, height=50, font_size=14 ) layout.add_widget(prod_btn) # Cancel button cancel_btn = Button( text="Cancel", background_color=(0.5, 0.5, 0.5, 1), size_hint_y=None, height=40, font_size=12 ) layout.add_widget(cancel_btn) popup = Popup( title="Select Video Generation Mode", content=layout, size_hint=(0.9, 0.8), auto_dismiss=False ) def start_test_mode(instance): popup.dismiss() self.generate_3d_video_test_mode() def start_production_mode(instance): popup.dismiss() self.generate_3d_video_production_mode() test_btn.bind(on_press=start_test_mode) prod_btn.bind(on_press=start_production_mode) cancel_btn.bind(on_press=lambda x: popup.dismiss()) popup.open()