Spaces:
Build error
Build error
| import os | |
| import gradio as gr | |
| import shutil | |
| from PIL import Image | |
| import tempfile | |
| import json | |
| import zipfile | |
| # Set the directory where files will be saved | |
| SAVE_DIR = os.path.abspath("saved_media") #make sure its the as media_folder Above | |
| # Ensure the save directory exists | |
| os.makedirs(SAVE_DIR, exist_ok=True) | |
| # Define supported file extensions | |
| SUPPORTED_EXTENSIONS = { | |
| "image": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"], | |
| "audio": [".mp3", ".wav", ".ogg"], | |
| "video": [".mp4", ".avi", ".mov", ".webm"], | |
| "model3d": [".glb", ".gltf", ".obj"] | |
| } | |
| def save_file(file): | |
| if file is None: | |
| return "No file uploaded.", gr.update() | |
| try: | |
| # Get the original filename and extension | |
| original_filename = os.path.basename(file.name) | |
| _, extension = os.path.splitext(original_filename) | |
| # Check if the file extension is supported | |
| if not any(extension.lower() in exts for exts in SUPPORTED_EXTENSIONS.values()): | |
| return f"Unsupported file type: {extension}", gr.update() | |
| # Create a unique filename to avoid overwriting | |
| base_name = os.path.splitext(original_filename)[0] | |
| counter = 1 | |
| new_filename = f"{base_name}{extension}" | |
| while os.path.exists(os.path.join(SAVE_DIR, new_filename)): | |
| new_filename = f"{base_name}_{counter}{extension}" | |
| counter += 1 | |
| # Copy the file from the temporary location to our save directory | |
| dest_path = os.path.join(SAVE_DIR, new_filename) | |
| shutil.copy2(file.name, dest_path) | |
| # Return success message and updated FileExplorer | |
| return f"File saved as {SAVE_DIR}/{new_filename}", gr.update(value=SAVE_DIR), gr.update(value=None) | |
| except Exception as e: | |
| return f"Error saving file: {str(e)}", gr.update(value=SAVE_DIR), gr.update() | |
| def view_file(file_path): | |
| """View a file and return appropriate outputs for each media type. | |
| Returns: (image, audio, video, message, model3d) | |
| """ | |
| if not file_path: | |
| return None, None, None, "No file selected.", None | |
| try: | |
| # FileExplorer returns relative path from root_dir, or could be full path | |
| # Handle both cases | |
| if os.path.isabs(file_path): | |
| full_path = file_path | |
| elif file_path.startswith(SAVE_DIR): | |
| full_path = file_path | |
| else: | |
| full_path = os.path.join(SAVE_DIR, file_path) | |
| # Normalize the path | |
| full_path = os.path.normpath(full_path) | |
| if not os.path.exists(full_path): | |
| return None, None, None, f"File not found: {full_path}", None | |
| _, extension = os.path.splitext(full_path) | |
| extension = extension.lower() | |
| if extension in SUPPORTED_EXTENSIONS["image"]: | |
| return Image.open(full_path), None, None, f"Viewing: {os.path.basename(full_path)}", None | |
| elif extension in SUPPORTED_EXTENSIONS["audio"]: | |
| return None, full_path, None, f"Viewing: {os.path.basename(full_path)}", None | |
| elif extension in SUPPORTED_EXTENSIONS["video"]: | |
| return None, None, full_path, f"Viewing: {os.path.basename(full_path)}", None | |
| elif extension in SUPPORTED_EXTENSIONS["model3d"]: | |
| return None, None, None, f"Viewing 3D: {os.path.basename(full_path)}", full_path | |
| else: | |
| return None, None, None, f"Unsupported file type: {extension}", None | |
| except Exception as e: | |
| return None, None, None, f"Error viewing file: {str(e)}", None | |
| def get_all_media_files(): | |
| """Get all media files from saved_media folder for use in dropdowns""" | |
| try: | |
| if not os.path.exists(SAVE_DIR): | |
| return [] | |
| files = os.listdir(SAVE_DIR) | |
| # Filter to only supported media files | |
| media_files = [] | |
| for f in files: | |
| ext = os.path.splitext(f)[1].lower() | |
| if any(ext in exts for exts in SUPPORTED_EXTENSIONS.values()): | |
| media_files.append(f) | |
| return sorted(media_files) | |
| except Exception as e: | |
| print(f"Error listing media files: {e}") | |
| return [] | |
| def refresh_file_explorer(): | |
| files = os.listdir(SAVE_DIR) | |
| return gr.update(value=files) | |
| def delete_file(file_path): | |
| if os.path.exists(file_path): | |
| os.remove(file_path) | |
| fileexplorerupdate = refresh_file_explorer() | |
| return fileexplorerupdate, f"{file_path} has been deleted." | |
| else: | |
| return f"{file_path} does not exist." | |
| def delete_file_and_refresh(filename): | |
| """Delete file and return updated dropdown choices""" | |
| if not filename: | |
| return gr.update(choices=get_all_media_files()), "No file selected" | |
| full_path = os.path.join(SAVE_DIR, filename) | |
| if os.path.exists(full_path): | |
| os.remove(full_path) | |
| return gr.update(choices=get_all_media_files(), value=None), f"Deleted: {filename}" | |
| return gr.update(choices=get_all_media_files()), f"File not found: {filename}" | |
| def save_file_and_refresh(file): | |
| """Save file and return updated dropdown choices for Browse tab""" | |
| if file is None: | |
| return "No file uploaded.", gr.update(), gr.update(value=None) | |
| try: | |
| original_filename = os.path.basename(file.name) | |
| _, extension = os.path.splitext(original_filename) | |
| if not any(extension.lower() in exts for exts in SUPPORTED_EXTENSIONS.values()): | |
| return f"Unsupported file type: {extension}", gr.update(), gr.update() | |
| base_name = os.path.splitext(original_filename)[0] | |
| counter = 1 | |
| new_filename = f"{base_name}{extension}" | |
| while os.path.exists(os.path.join(SAVE_DIR, new_filename)): | |
| new_filename = f"{base_name}_{counter}{extension}" | |
| counter += 1 | |
| dest_path = os.path.join(SAVE_DIR, new_filename) | |
| shutil.copy2(file.name, dest_path) | |
| # Return updated dropdown choices | |
| return f"File saved: {new_filename}", gr.update(choices=get_all_media_files()), gr.update(value=None) | |
| except Exception as e: | |
| return f"Error saving file: {str(e)}", gr.update(), gr.update() | |
| def upload_file_or_bundle(file): | |
| """ | |
| Unified upload handler that handles both media files and zip bundles. | |
| Returns: (status, dropdown_update, file_input_clear, config_json, extracted_files) | |
| """ | |
| if file is None: | |
| return "No file uploaded.", gr.update(), gr.update(value=None), None, "" | |
| try: | |
| original_filename = os.path.basename(file.name) | |
| _, extension = os.path.splitext(original_filename) | |
| ext_lower = extension.lower() | |
| # Check if it's a zip bundle | |
| if ext_lower == ".zip": | |
| try: | |
| config, extracted_files = import_config_with_media(file.name) | |
| config_json = json.dumps(config, indent=2) | |
| files_str = "\n".join(extracted_files) if extracted_files else "No new files extracted (all already existed)" | |
| status = f"Bundle imported! Config loaded, {len(extracted_files)} new media files extracted." | |
| return ( | |
| status, | |
| gr.update(choices=get_all_media_files()), | |
| gr.update(value=None), | |
| config_json, | |
| files_str | |
| ) | |
| except FileNotFoundError as e: | |
| return f"Error: {str(e)}", gr.update(), gr.update(), None, "" | |
| except Exception as e: | |
| return f"Error importing bundle: {str(e)}", gr.update(), gr.update(), None, "" | |
| # Handle regular media files | |
| if not any(ext_lower in exts for exts in SUPPORTED_EXTENSIONS.values()): | |
| return f"Unsupported file type: {extension}", gr.update(), gr.update(), None, "" | |
| base_name = os.path.splitext(original_filename)[0] | |
| counter = 1 | |
| new_filename = f"{base_name}{extension}" | |
| while os.path.exists(os.path.join(SAVE_DIR, new_filename)): | |
| new_filename = f"{base_name}_{counter}{extension}" | |
| counter += 1 | |
| dest_path = os.path.join(SAVE_DIR, new_filename) | |
| shutil.copy2(file.name, dest_path) | |
| return ( | |
| f"File saved: {new_filename}", | |
| gr.update(choices=get_all_media_files()), | |
| gr.update(value=None), | |
| None, | |
| "" | |
| ) | |
| except Exception as e: | |
| return f"Error: {str(e)}", gr.update(), gr.update(), None, "" | |
| def export_config_with_media_wrapper(config_json): | |
| """Wrapper for export that provides status message along with the file""" | |
| from my_text_game_engine_attempt import export_config_with_media | |
| if not config_json or not config_json.strip(): | |
| return None, "Please paste a config JSON to export" | |
| try: | |
| zip_path = export_config_with_media(config_json) | |
| return zip_path, f"Export successful! Bundle ready for download." | |
| except json.JSONDecodeError as e: | |
| return None, f"Invalid JSON: {str(e)}" | |
| except Exception as e: | |
| return None, f"Export failed: {str(e)}" | |
| def import_config_with_media(zip_path): | |
| global SAVE_DIR | |
| target_folder = SAVE_DIR | |
| """ | |
| Import the config JSON and media files from a zip file. | |
| Extract only the media files that don't already exist in the target folder. | |
| :param zip_path: Path to the zip file containing the config and media files | |
| :param target_folder: Path to the folder where media files should be extracted | |
| :return: Tuple containing the loaded config (as a dictionary) and a list of newly extracted files | |
| """ | |
| config = None | |
| extracted_files = [] | |
| with tempfile.TemporaryDirectory() as temp_dir: | |
| # Extract all files to a temporary directory | |
| with zipfile.ZipFile(zip_path, 'r') as zip_ref: | |
| zip_ref.extractall(temp_dir) | |
| # Load the config (check both config.json and game_config.json for compatibility) | |
| config_path = os.path.join(temp_dir, 'config.json') | |
| alt_config_path = os.path.join(temp_dir, 'game_config.json') | |
| if os.path.exists(config_path): | |
| with open(config_path, 'r') as f: | |
| config = json.load(f) | |
| elif os.path.exists(alt_config_path): | |
| with open(alt_config_path, 'r') as f: | |
| config = json.load(f) | |
| else: | |
| raise FileNotFoundError("config.json (or game_config.json) not found in the zip file") | |
| # Create the target folder if it doesn't exist | |
| os.makedirs(target_folder, exist_ok=True) | |
| # Copy media files that don't already exist in the target folder | |
| config_files = {'config.json', 'game_config.json'} | |
| for root, _, files in os.walk(temp_dir): | |
| for file in files: | |
| if file not in config_files: | |
| src_path = os.path.join(root, file) | |
| dst_path = os.path.join(target_folder, file) | |
| if not os.path.exists(dst_path): | |
| shutil.copy2(src_path, dst_path) | |
| extracted_files.append(file) | |
| return config, extracted_files |