awacke1 commited on
Commit
49f7fb7
ยท
verified ยท
1 Parent(s): e74a5ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -29
app.py CHANGED
@@ -31,10 +31,8 @@ from PIL import Image
31
  # Configuration & Constants
32
  # ==============================================================================
33
 
34
- # Patch asyncio for nesting
35
  nest_asyncio.apply()
36
 
37
- # Page Config
38
  st.set_page_config(
39
  page_title="๐Ÿค–๐Ÿ—๏ธ Shared World Builder ๐Ÿ†",
40
  page_icon="๐Ÿ—๏ธ",
@@ -42,14 +40,12 @@ st.set_page_config(
42
  initial_sidebar_state="expanded"
43
  )
44
 
45
- # General Constants
46
  icons = '๐Ÿค–๐Ÿ—๏ธ๐Ÿ—ฃ๏ธ๐Ÿ’พ'
47
  Site_Name = '๐Ÿค–๐Ÿ—๏ธ Shared World Builder ๐Ÿ—ฃ๏ธ'
48
  START_ROOM = "World Lobby ๐ŸŒ"
49
  MEDIA_DIR = "."
50
  STATE_FILE = "user_state.txt"
51
 
52
- # User/Chat Constants
53
  FUN_USERNAMES = {
54
  "BuilderBot ๐Ÿค–": "en-US-AriaNeural", "WorldWeaver ๐Ÿ•ธ๏ธ": "en-US-JennyNeural",
55
  "Terraformer ๐ŸŒฑ": "en-GB-SoniaNeural", "SkyArchitect โ˜๏ธ": "en-AU-NatashaNeural",
@@ -59,22 +55,16 @@ FUN_USERNAMES = {
59
  }
60
  EDGE_TTS_VOICES = list(set(FUN_USERNAMES.values()))
61
  CHAT_DIR = "chat_logs"
62
-
63
- # Audio Constants
64
  AUDIO_CACHE_DIR = "audio_cache"
65
  AUDIO_DIR = "audio_logs"
66
-
67
- # World Builder Constants
68
- SAVED_WORLDS_DIR = "saved_worlds" # Corrected from SAVED_WORLDS0
69
  HISTORY_LOG_DIR = "history_logs"
70
  PLOT_WIDTH = 50.0
71
  PLOT_DEPTH = 50.0
72
  WORLD_STATE_FILE_MD_PREFIX = "๐ŸŒ_"
73
 
74
- # File Emojis
75
  FILE_EMOJIS = {"md": "๐Ÿ“", "mp3": "๐ŸŽต", "png": "๐Ÿ–ผ๏ธ", "mp4": "๐ŸŽฅ", "zip": "๐Ÿ“ฆ", "json": "๐Ÿ“„"}
76
 
77
- # Mapping Emojis to Primitive Types
78
  PRIMITIVE_MAP = {
79
  "๐ŸŒณ": "Tree", "๐Ÿ—ฟ": "Rock", "๐Ÿ›๏ธ": "Simple House", "๐ŸŒฒ": "Pine Tree", "๐Ÿงฑ": "Brick Wall",
80
  "๐Ÿ”ต": "Sphere", "๐Ÿ“ฆ": "Cube", "๐Ÿงด": "Cylinder", "๐Ÿฆ": "Cone", "๐Ÿฉ": "Torus",
@@ -82,11 +72,9 @@ PRIMITIVE_MAP = {
82
  "๐Ÿ—ผ": "Tower", "๐Ÿšง": "Barrier", "โ›ฒ": "Fountain", "๐Ÿฎ": "Lantern", "๐Ÿชง": "Sign Post"
83
  }
84
 
85
- # Directories
86
  for d in [CHAT_DIR, AUDIO_DIR, AUDIO_CACHE_DIR, SAVED_WORLDS_DIR, HISTORY_LOG_DIR]:
87
  os.makedirs(d, exist_ok=True)
88
 
89
- # Global State & Locks
90
  world_objects_lock = threading.Lock()
91
  world_objects = defaultdict(dict)
92
  connected_clients = set()
@@ -769,6 +757,12 @@ async def websocket_handler(websocket, path):
769
  broadcast_payload = json.dumps({"type": "player_moved", "payload": {"username": sender_username, "id": client_id, "position": pos_data, "rotation": rot_data}})
770
  await broadcast_message(broadcast_payload, exclude_id=client_id)
771
 
 
 
 
 
 
 
772
  except json.JSONDecodeError:
773
  print(f"WS Invalid JSON from {client_id}: {message[:100]}...")
774
  except Exception as e:
@@ -927,6 +921,16 @@ def render_sidebar():
927
  st.markdown("---")
928
  st.header("๐Ÿ—๏ธ Build Tools")
929
  st.caption("Select an object to place.")
 
 
 
 
 
 
 
 
 
 
930
  cols = st.columns(5)
931
  col_idx = 0
932
  current_tool = st.session_state.get('selected_object', 'None')
@@ -934,25 +938,30 @@ def render_sidebar():
934
  button_key = f"primitive_{name}"
935
  button_type = "primary" if current_tool == name else "secondary"
936
  if cols[col_idx % 5].button(emoji, key=button_key, help=name, type=button_type, use_container_width=True):
937
- if st.session_state.get('selected_object', 'None') != name:
938
- st.session_state.selected_object = name
939
- run_async(lambda name_arg=name: streamlit_js_eval(
940
- f"updateSelectedObjectType({json.dumps(name_arg)});",
941
- key=f"update_tool_js_{name_arg}"
942
- ))
943
- run_async(broadcast_world_update)
944
- st.rerun()
 
 
 
945
  col_idx += 1
946
  st.markdown("---")
947
  if st.button("๐Ÿšซ Clear Tool", key="clear_tool", use_container_width=True):
948
- if st.session_state.get('selected_object', 'None') != 'None':
949
- st.session_state.selected_object = 'None'
950
- run_async(lambda: streamlit_js_eval(
951
- "updateSelectedObjectType('None');",
952
- key="update_tool_js_none"
953
- ))
954
- run_async(broadcast_world_update)
955
- st.rerun()
 
 
956
 
957
  st.markdown("---")
958
  st.header("๐Ÿ—ฃ๏ธ Voice & User")
 
31
  # Configuration & Constants
32
  # ==============================================================================
33
 
 
34
  nest_asyncio.apply()
35
 
 
36
  st.set_page_config(
37
  page_title="๐Ÿค–๐Ÿ—๏ธ Shared World Builder ๐Ÿ†",
38
  page_icon="๐Ÿ—๏ธ",
 
40
  initial_sidebar_state="expanded"
41
  )
42
 
 
43
  icons = '๐Ÿค–๐Ÿ—๏ธ๐Ÿ—ฃ๏ธ๐Ÿ’พ'
44
  Site_Name = '๐Ÿค–๐Ÿ—๏ธ Shared World Builder ๐Ÿ—ฃ๏ธ'
45
  START_ROOM = "World Lobby ๐ŸŒ"
46
  MEDIA_DIR = "."
47
  STATE_FILE = "user_state.txt"
48
 
 
49
  FUN_USERNAMES = {
50
  "BuilderBot ๐Ÿค–": "en-US-AriaNeural", "WorldWeaver ๐Ÿ•ธ๏ธ": "en-US-JennyNeural",
51
  "Terraformer ๐ŸŒฑ": "en-GB-SoniaNeural", "SkyArchitect โ˜๏ธ": "en-AU-NatashaNeural",
 
55
  }
56
  EDGE_TTS_VOICES = list(set(FUN_USERNAMES.values()))
57
  CHAT_DIR = "chat_logs"
 
 
58
  AUDIO_CACHE_DIR = "audio_cache"
59
  AUDIO_DIR = "audio_logs"
60
+ SAVED_WORLDS_DIR = "saved_worlds"
 
 
61
  HISTORY_LOG_DIR = "history_logs"
62
  PLOT_WIDTH = 50.0
63
  PLOT_DEPTH = 50.0
64
  WORLD_STATE_FILE_MD_PREFIX = "๐ŸŒ_"
65
 
 
66
  FILE_EMOJIS = {"md": "๐Ÿ“", "mp3": "๐ŸŽต", "png": "๐Ÿ–ผ๏ธ", "mp4": "๐ŸŽฅ", "zip": "๐Ÿ“ฆ", "json": "๐Ÿ“„"}
67
 
 
68
  PRIMITIVE_MAP = {
69
  "๐ŸŒณ": "Tree", "๐Ÿ—ฟ": "Rock", "๐Ÿ›๏ธ": "Simple House", "๐ŸŒฒ": "Pine Tree", "๐Ÿงฑ": "Brick Wall",
70
  "๐Ÿ”ต": "Sphere", "๐Ÿ“ฆ": "Cube", "๐Ÿงด": "Cylinder", "๐Ÿฆ": "Cone", "๐Ÿฉ": "Torus",
 
72
  "๐Ÿ—ผ": "Tower", "๐Ÿšง": "Barrier", "โ›ฒ": "Fountain", "๐Ÿฎ": "Lantern", "๐Ÿชง": "Sign Post"
73
  }
74
 
 
75
  for d in [CHAT_DIR, AUDIO_DIR, AUDIO_CACHE_DIR, SAVED_WORLDS_DIR, HISTORY_LOG_DIR]:
76
  os.makedirs(d, exist_ok=True)
77
 
 
78
  world_objects_lock = threading.Lock()
79
  world_objects = defaultdict(dict)
80
  connected_clients = set()
 
757
  broadcast_payload = json.dumps({"type": "player_moved", "payload": {"username": sender_username, "id": client_id, "position": pos_data, "rotation": rot_data}})
758
  await broadcast_message(broadcast_payload, exclude_id=client_id)
759
 
760
+ elif msg_type == "tool_selected":
761
+ tool_type = payload.get("tool_type")
762
+ if tool_type in PRIMITIVE_MAP.values() or tool_type == "None":
763
+ st.session_state.selected_object = tool_type
764
+ print(f"Tool updated to {tool_type} for {sender_username}")
765
+
766
  except json.JSONDecodeError:
767
  print(f"WS Invalid JSON from {client_id}: {message[:100]}...")
768
  except Exception as e:
 
921
  st.markdown("---")
922
  st.header("๐Ÿ—๏ธ Build Tools")
923
  st.caption("Select an object to place.")
924
+ # Hidden selectbox to sync tool state
925
+ tool_options = ['None'] + list(PRIMITIVE_MAP.values())
926
+ selected_tool = st.selectbox("Selected Tool", options=tool_options, index=tool_options.index(st.session_state.get('selected_object', 'None')), key="tool_select", label_visibility="collapsed")
927
+ if selected_tool != st.session_state.selected_object:
928
+ st.session_state.selected_object = selected_tool
929
+ run_async(lambda: streamlit_js_eval(
930
+ f"updateSelectedObjectType({json.dumps(selected_tool)});",
931
+ key=f"update_tool_js_{selected_tool}"
932
+ ))
933
+
934
  cols = st.columns(5)
935
  col_idx = 0
936
  current_tool = st.session_state.get('selected_object', 'None')
 
938
  button_key = f"primitive_{name}"
939
  button_type = "primary" if current_tool == name else "secondary"
940
  if cols[col_idx % 5].button(emoji, key=button_key, help=name, type=button_type, use_container_width=True):
941
+ # Update tool via JavaScript without rerun
942
+ run_async(lambda name_arg=name: streamlit_js_eval(
943
+ f"""
944
+ updateSelectedObjectType('{name_arg}');
945
+ websocket.send(JSON.stringify({{
946
+ type: 'tool_selected',
947
+ payload: {{ tool_type: '{name_arg}', username: window.USERNAME }}
948
+ }}));
949
+ """,
950
+ key=f"update_tool_js_{name_arg}"
951
+ ))
952
  col_idx += 1
953
  st.markdown("---")
954
  if st.button("๐Ÿšซ Clear Tool", key="clear_tool", use_container_width=True):
955
+ run_async(lambda: streamlit_js_eval(
956
+ """
957
+ updateSelectedObjectType('None');
958
+ websocket.send(JSON.stringify({
959
+ type: 'tool_selected',
960
+ payload: { tool_type: 'None', username: window.USERNAME }
961
+ }));
962
+ """,
963
+ key="update_tool_js_none"
964
+ ))
965
 
966
  st.markdown("---")
967
  st.header("๐Ÿ—ฃ๏ธ Voice & User")