Spaces:
Sleeping
Sleeping
# app.py | |
import streamlit as st | |
import streamlit.components.v1 as components | |
import os | |
import json # To safely embed the python variable into JS | |
# --- 1. Set Page Configuration (Set first!) --- | |
st.set_page_config( | |
page_title="Three.js Editor", | |
layout="wide" # Use the full screen width | |
) | |
# --- Initialize Session State --- | |
if 'selected_object' not in st.session_state: | |
st.session_state.selected_object = 'None' # Default selection | |
# --- Sidebar Controls --- | |
with st.sidebar: | |
st.title("๐ ๏ธ Controls & State") | |
st.caption("Select an object type and click on the ground in the main view to place it.") | |
# Define available object types (keys should ideally match JS functions/identifiers) | |
object_types = ["None", "Simple House", "Tree", "Rock", "Fence Post"] # Add more as needed | |
# Selectbox to choose object type - this updates session_state on change | |
selected = st.selectbox( | |
"Select Object to Place:", | |
options=object_types, | |
key='selected_object' # Link to session state key | |
) | |
st.write("---") | |
st.header("Current State:") | |
st.write(f"Selected Object Type: **{st.session_state.selected_object}**") | |
# Add more state tracking here later if needed | |
st.info("Use WASD/Arrows in the main view if player movement is enabled in JS.") | |
# --- Main Area for the 3D View --- | |
st.header("๐๏ธ Three.js Primitive Builder") | |
# --- Load and Prepare HTML --- | |
html_file_path = 'index.html' | |
try: | |
with open(html_file_path, 'r', encoding='utf-8') as f: | |
html_template = f.read() | |
# --- Inject Python state into JavaScript --- | |
# We'll add a script tag to set a global JS variable before the main script runs | |
js_injection_script = f""" | |
<script> | |
// Set this global variable based on Streamlit state BEFORE the main script runs | |
window.SELECTED_OBJECT_TYPE = {json.dumps(st.session_state.selected_object)}; | |
console.log("Streamlit selected object:", window.SELECTED_OBJECT_TYPE); | |
</script> | |
""" | |
# Insert the injection script just before the closing </head> or starting <script type="module"> | |
# A simple approach: find the main script tag and insert before it. | |
# More robust: add a placeholder like in index.html | |
# For now, let's find the module script tag: | |
module_script_tag = '<script type="module">' | |
if module_script_tag in html_template: | |
# Inject our script right before the main module script | |
html_content_with_state = html_template.replace( | |
module_script_tag, | |
js_injection_script + "\n" + module_script_tag, | |
1 # Replace only the first occurrence | |
) | |
else: | |
# Fallback: inject before closing head (less ideal if script needs DOM) | |
html_content_with_state = html_template.replace('</head>', js_injection_script + '\n</head>', 1) | |
# --- Embed HTML Component --- | |
components.html( | |
html_content_with_state, | |
height=750, # Adjust height as needed | |
scrolling=False | |
) | |
except FileNotFoundError: | |
st.error(f"Error: Could not find the file '{html_file_path}'.") | |
st.warning("Please make sure `index.html` is in the same directory as `app.py`.") | |
except Exception as e: | |
st.error(f"An error occurred: {e}") | |
st.exception(e) # Show full traceback for debugging |