awacke1 commited on
Commit
9f9622d
·
verified ·
1 Parent(s): 7cdfaeb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +178 -7
app.py CHANGED
@@ -22,6 +22,81 @@ CSV_COLUMNS = [
22
  'rot_x', 'rot_y', 'rot_z', 'rot_order'
23
  ]
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  # 🗂️ Ensure directory for plots exists
26
  os.makedirs(SAVE_DIR, exist_ok=True)
27
 
@@ -132,8 +207,11 @@ game_state = get_game_state()
132
 
133
  # 🧠 Session state defaults
134
  st.session_state.setdefault('selected_object','None')
 
135
  st.session_state.setdefault('new_plot_name','')
136
  st.session_state.setdefault('js_save_data_result',None)
 
 
137
 
138
  # 🔄 Load everything
139
  plots_metadata = load_plot_metadata()
@@ -144,6 +222,7 @@ for p in plots_metadata:
144
  # 🖥️ Sidebar UI
145
  with st.sidebar:
146
  st.title("🏗️ World Controls")
 
147
  st.header("📍 Navigate Plots")
148
  cols = st.columns(2)
149
  i = 0
@@ -160,11 +239,59 @@ with st.sidebar:
160
 
161
  st.markdown("---")
162
  st.header("🌲 Place Objects")
163
- opts = ["None","Simple House","Tree","Rock","Fence Post"]
164
- idx = opts.index(st.session_state.selected_object) if st.session_state.selected_object in opts else 0
165
- sel = st.selectbox("Select:", opts, index=idx, key="selected_object_widget")
166
- if sel != st.session_state.selected_object:
167
- st.session_state.selected_object = sel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  st.markdown("---")
170
  st.header("💾 Save Work")
@@ -172,6 +299,15 @@ with st.sidebar:
172
  from streamlit_js_eval import streamlit_js_eval
173
  streamlit_js_eval(js_code="getSaveDataAndPosition();", key="js_save_processor")
174
  st.rerun()
 
 
 
 
 
 
 
 
 
175
 
176
  # 📨 Handle incoming save data
177
  raw = st.session_state.get("js_save_processor")
@@ -200,6 +336,35 @@ if raw:
200
  st.session_state.js_save_processor=None
201
  if ok: st.rerun()
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  # 🏠 Main view
204
  st.header("🌍 Infinite Shared 3D World")
205
  st.caption("➡️ Explore, click to build, 💾 to save!")
@@ -209,6 +374,8 @@ state = {
209
  "ALL_INITIAL_OBJECTS": all_initial_objects,
210
  "PLOTS_METADATA": plots_metadata,
211
  "SELECTED_OBJECT_TYPE": st.session_state.selected_object,
 
 
212
  "PLOT_WIDTH": PLOT_WIDTH,
213
  "PLOT_DEPTH": PLOT_DEPTH,
214
  "GAME_STATE": game_state.get_state()
@@ -222,13 +389,17 @@ try:
222
  window.ALL_INITIAL_OBJECTS = {json.dumps(state['ALL_INITIAL_OBJECTS'])};
223
  window.PLOTS_METADATA = {json.dumps(state['PLOTS_METADATA'])};
224
  window.SELECTED_OBJECT_TYPE = {json.dumps(state['SELECTED_OBJECT_TYPE'])};
 
 
225
  window.PLOT_WIDTH = {json.dumps(state['PLOT_WIDTH'])};
226
  window.PLOT_DEPTH = {json.dumps(state['PLOT_DEPTH'])};
227
  window.GAME_STATE = {json.dumps(state['GAME_STATE'])};
228
  console.log('👍 State injected!', {{
229
  objs: window.ALL_INITIAL_OBJECTS.length,
230
  plots: window.PLOTS_METADATA.length,
231
- gs: window.GAME_STATE.length
 
 
232
  }});
233
  </script>
234
  """
@@ -237,4 +408,4 @@ try:
237
  except FileNotFoundError:
238
  st.error("❌ index.html missing!")
239
  except Exception as e:
240
- st.error(f"😱 HTML inject failed: {e}")
 
22
  'rot_x', 'rot_y', 'rot_z', 'rot_order'
23
  ]
24
 
25
+ # 🎨 Model categories and types
26
+ MODEL_CATEGORIES = {
27
+ "None": ["None"],
28
+ "Buildings": [
29
+ "Simple House",
30
+ "Cyberpunk Wall Panel",
31
+ "Modular Hab Block",
32
+ "MegaCorp Skyscraper",
33
+ "Castle Wall Section",
34
+ "Wooden Door",
35
+ "House Roof Section",
36
+ "Concrete Bunker Wall",
37
+ "Damaged House Facade"
38
+ ],
39
+ "Nature": [
40
+ "Tree",
41
+ "Rock",
42
+ "Pine Tree",
43
+ "Boulder",
44
+ "Alien Plant",
45
+ "Floating Rock Platform",
46
+ "Rubble Pile"
47
+ ],
48
+ "Props": [
49
+ "Fence Post",
50
+ "Rooftop AC Unit",
51
+ "Holographic Window Display",
52
+ "Jersey Barrier",
53
+ "Oil Drum",
54
+ "Canned Food",
55
+ "Treasure Chest",
56
+ "Wall Torch",
57
+ "Bone Pile"
58
+ ],
59
+ "Characters": [
60
+ "King Figure",
61
+ "Soldier Figure",
62
+ "Mage Figure",
63
+ "Zombie Figure",
64
+ "Survivor Figure",
65
+ "Dwarf Miner Figure",
66
+ "Undead Knight Figure",
67
+ "Hero Figure"
68
+ ],
69
+ "Vehicles": [
70
+ "Wooden Cart",
71
+ "Ballista",
72
+ "Siege Tower",
73
+ "Buggy Frame",
74
+ "Motorbike",
75
+ "Hover Bike",
76
+ "APC",
77
+ "Sand Boat"
78
+ ],
79
+ "Weapons": [
80
+ "Makeshift Machete",
81
+ "Pistol Body",
82
+ "Scope Attachment",
83
+ "Laser Pistol",
84
+ "Energy Sword",
85
+ "Dwarven Axe",
86
+ "Magic Staff"
87
+ ],
88
+ "Effects": [
89
+ "Candle Flame",
90
+ "Dust Cloud",
91
+ "Blood Splat Decal",
92
+ "Burning Barrel Fire",
93
+ "Warp Tunnel Effect",
94
+ "Laser Beam",
95
+ "Gold Sparkle",
96
+ "Steam Vent"
97
+ ]
98
+ }
99
+
100
  # 🗂️ Ensure directory for plots exists
101
  os.makedirs(SAVE_DIR, exist_ok=True)
102
 
 
207
 
208
  # 🧠 Session state defaults
209
  st.session_state.setdefault('selected_object','None')
210
+ st.session_state.setdefault('selected_category','None')
211
  st.session_state.setdefault('new_plot_name','')
212
  st.session_state.setdefault('js_save_data_result',None)
213
+ st.session_state.setdefault('custom_scale', 1.0)
214
+ st.session_state.setdefault('custom_rotation_y', 0)
215
 
216
  # 🔄 Load everything
217
  plots_metadata = load_plot_metadata()
 
222
  # 🖥️ Sidebar UI
223
  with st.sidebar:
224
  st.title("🏗️ World Controls")
225
+
226
  st.header("📍 Navigate Plots")
227
  cols = st.columns(2)
228
  i = 0
 
239
 
240
  st.markdown("---")
241
  st.header("🌲 Place Objects")
242
+
243
+ # 📂 Category selector
244
+ category_list = list(MODEL_CATEGORIES.keys())
245
+ selected_category = st.selectbox(
246
+ "Category:",
247
+ category_list,
248
+ index=category_list.index(st.session_state.selected_category) if st.session_state.selected_category in category_list else 0,
249
+ key="selected_category_widget"
250
+ )
251
+
252
+ if selected_category != st.session_state.selected_category:
253
+ st.session_state.selected_category = selected_category
254
+ if st.session_state.selected_category != "None":
255
+ # Default to first item in the new category
256
+ st.session_state.selected_object = MODEL_CATEGORIES[selected_category][0]
257
+
258
+ # 🖼️ Object selector within the category
259
+ if selected_category in MODEL_CATEGORIES:
260
+ object_list = MODEL_CATEGORIES[selected_category]
261
+ current_object = st.session_state.selected_object
262
+ if current_object not in object_list:
263
+ current_object = object_list[0]
264
+
265
+ selected_object = st.selectbox(
266
+ "Select:",
267
+ object_list,
268
+ index=object_list.index(current_object) if current_object in object_list else 0,
269
+ key="selected_object_widget"
270
+ )
271
+
272
+ if selected_object != st.session_state.selected_object:
273
+ st.session_state.selected_object = selected_object
274
+
275
+ # ↕️ Scale slider (not shown for the None selection)
276
+ if st.session_state.selected_object != "None":
277
+ st.session_state.custom_scale = st.slider(
278
+ "Scale:",
279
+ min_value=0.2,
280
+ max_value=3.0,
281
+ value=st.session_state.custom_scale,
282
+ step=0.1,
283
+ key="scale_slider"
284
+ )
285
+
286
+ # 🔄 Rotation slider (Y-axis)
287
+ st.session_state.custom_rotation_y = st.slider(
288
+ "Rotation:",
289
+ min_value=0,
290
+ max_value=359,
291
+ value=st.session_state.custom_rotation_y,
292
+ step=15,
293
+ key="rotation_slider"
294
+ )
295
 
296
  st.markdown("---")
297
  st.header("💾 Save Work")
 
299
  from streamlit_js_eval import streamlit_js_eval
300
  streamlit_js_eval(js_code="getSaveDataAndPosition();", key="js_save_processor")
301
  st.rerun()
302
+
303
+ # 📝 New plot naming
304
+ with st.expander("Create Named Plot"):
305
+ st.text_input("New Plot Name:", key="new_plot_name")
306
+ if st.button("Create at Current Position"):
307
+ if st.session_state.new_plot_name.strip():
308
+ from streamlit_js_eval import streamlit_js_eval
309
+ streamlit_js_eval(js_code="getSaveDataForNamedPlot();", key="named_plot_processor")
310
+ st.rerun()
311
 
312
  # 📨 Handle incoming save data
313
  raw = st.session_state.get("js_save_processor")
 
336
  st.session_state.js_save_processor=None
337
  if ok: st.rerun()
338
 
339
+ # 📨 Handle named plot data
340
+ named_raw = st.session_state.get("named_plot_processor")
341
+ if named_raw:
342
+ st.info("📬 Got data for named plot!")
343
+ ok=False
344
+ try:
345
+ pay = json.loads(named_raw) if isinstance(named_raw,str) else named_raw
346
+ pos, objs = pay.get('playerPosition'), pay.get('objectsToSave')
347
+ if isinstance(objs,list) and pos and st.session_state.new_plot_name.strip():
348
+ gx, gz = math.floor(pos['x']/PLOT_WIDTH), math.floor(pos['z']/PLOT_DEPTH)
349
+ name = st.session_state.new_plot_name.strip().replace(' ', '_')
350
+ fn = f"plot_X{gx}_Z{gz}_{name}.csv"
351
+ if save_plot_data(fn, objs, gx*PLOT_WIDTH, gz*PLOT_DEPTH):
352
+ load_plot_metadata.clear()
353
+ try:
354
+ from streamlit_js_eval import streamlit_js_eval
355
+ streamlit_js_eval(js_code="resetNewlyPlacedObjects();", key="reset_js")
356
+ except:
357
+ pass
358
+ game_state.update_state(objs)
359
+ ok=True
360
+ st.session_state.new_plot_name = ""
361
+ if not ok:
362
+ st.error("❌ Named plot save error")
363
+ except Exception as e:
364
+ st.error(f"Named plot err: {e}")
365
+ st.session_state.named_plot_processor=None
366
+ if ok: st.rerun()
367
+
368
  # 🏠 Main view
369
  st.header("🌍 Infinite Shared 3D World")
370
  st.caption("➡️ Explore, click to build, 💾 to save!")
 
374
  "ALL_INITIAL_OBJECTS": all_initial_objects,
375
  "PLOTS_METADATA": plots_metadata,
376
  "SELECTED_OBJECT_TYPE": st.session_state.selected_object,
377
+ "CUSTOM_SCALE": st.session_state.custom_scale,
378
+ "CUSTOM_ROTATION_Y": st.session_state.custom_rotation_y * (math.pi / 180), # Convert to radians
379
  "PLOT_WIDTH": PLOT_WIDTH,
380
  "PLOT_DEPTH": PLOT_DEPTH,
381
  "GAME_STATE": game_state.get_state()
 
389
  window.ALL_INITIAL_OBJECTS = {json.dumps(state['ALL_INITIAL_OBJECTS'])};
390
  window.PLOTS_METADATA = {json.dumps(state['PLOTS_METADATA'])};
391
  window.SELECTED_OBJECT_TYPE = {json.dumps(state['SELECTED_OBJECT_TYPE'])};
392
+ window.CUSTOM_SCALE = {json.dumps(state['CUSTOM_SCALE'])};
393
+ window.CUSTOM_ROTATION_Y = {json.dumps(state['CUSTOM_ROTATION_Y'])};
394
  window.PLOT_WIDTH = {json.dumps(state['PLOT_WIDTH'])};
395
  window.PLOT_DEPTH = {json.dumps(state['PLOT_DEPTH'])};
396
  window.GAME_STATE = {json.dumps(state['GAME_STATE'])};
397
  console.log('👍 State injected!', {{
398
  objs: window.ALL_INITIAL_OBJECTS.length,
399
  plots: window.PLOTS_METADATA.length,
400
+ gs: window.GAME_STATE.length,
401
+ scale: window.CUSTOM_SCALE,
402
+ rotation: window.CUSTOM_ROTATION_Y
403
  }});
404
  </script>
405
  """
 
408
  except FileNotFoundError:
409
  st.error("❌ index.html missing!")
410
  except Exception as e:
411
+ st.error(f"😱 HTML inject failed: {e}")