import streamlit as st import os, base64, shutil, random from pathlib import Path @st.cache_data def load_aframe_and_extras(): return """ """ @st.cache_data def encode_file(path): with open(path,'rb') as f: return base64.b64encode(f.read()).decode() def create_aframe_entity(stem, ext, pos): # static random Y rotation, scale fills 1×1 tile ry = random.uniform(0,360) if ext == 'obj': return (f'') if ext in ('glb','gltf'): return (f'') return '' @st.cache_data def generate_tilemap(files, dirpath, gw=8, gh=8): img_exts = ['webp','png'] model_exts = ['obj','glb','gltf'] vid_exts = ['mp4'] imgs = [f for f in files if f.split('.')[-1] in img_exts] models = [f for f in files if f.split('.')[-1] in model_exts] vids = [f for f in files if f.split('.')[-1] in vid_exts] assets = "" for f in files: stem = Path(f).stem; ext=f.split('.')[-1] data=encode_file(os.path.join(dirpath,f)) if ext in model_exts: assets += (f'') elif ext in img_exts: assets += f'' elif ext in vid_exts: assets += (f'') assets += "" entities = "" sx=-gw/2; sz=-gh/2 for i in range(gw): for j in range(gh): x,y,z = sx+i,0,sz+j # ground image if imgs: img=random.choice(imgs); s=Path(img).stem entities += (f'') # model if models: m=random.choice(models); ext=m.split('.')[-1]; s=Path(m).stem entities += create_aframe_entity(s,ext,f"{x} 0.5 {z}") # video if vids: v=random.choice(vids); s=Path(v).stem entities += (f'') return assets, entities def main(): st.set_page_config(layout="wide") with st.sidebar: st.markdown("### ⬆️ Upload 3D / media files") ups = st.file_uploader("Add files:", accept_multiple_files=True) st.markdown("### 🎮 Camera Buttons") # 3×3 grid of buttons for qwe/asd/zxc rows = [ [('Q','rotateY+'), ('W','forward'), ('E','rotateY-')], [('A','left'), ('S','reset'), ('D','right')], [('Z','rotateZ+'),('X','backward'),('C','rotateZ-')] ] for row in rows: cols = st.columns(3) for (btn,cmd),col in zip(row, cols): col.button(btn, on_click=lambda c=cmd: st.session_state.update({'camera_move':c})) st.markdown("### 🗺️ Grid is fixed at 8×8") st.markdown("### 📁 Directory") directory = st.text_input("Path:", ".", key="dir") if not os.path.isdir(directory): st.sidebar.error("Invalid directory") return types = ['obj','glb','gltf','webp','png','mp4'] if ups: for up in ups: ext=Path(up.name).suffix.lower()[1:] if ext in types: with open(os.path.join(directory,up.name),'wb') as f: shutil.copyfileobj(up,f) st.sidebar.success(f"Uploaded {up.name}") else: st.sidebar.warning(f"Skipped {up.name}") files = [f for f in os.listdir(directory) if f.split('.')[-1] in types] # spotlight height spot_h = max(8,8)*1.5 # build scene scene = f""" """ assets, ents = generate_tilemap(files, directory, 8, 8) scene += assets + ents + "" # apply button or key moves cmd = st.session_state.get('camera_move') if cmd: scene += f"" st.session_state.pop('camera_move') # loader for OBJ/glTF loader = '' st.components.v1.html( load_aframe_and_extras() + loader + scene, height=650 ) if __name__ == "__main__": main()