awacke1 commited on
Commit
5e7c5f7
·
verified ·
1 Parent(s): 53c7232

Update bak.05082025.app.py

Browse files
Files changed (1) hide show
  1. bak.05082025.app.py +209 -76
bak.05082025.app.py CHANGED
@@ -9,34 +9,152 @@ def load_aframe_and_extras():
9
  <script src="https://unpkg.com/[email protected]/dist/aframe-event-set-component.min.js"></script>
10
  <script>
11
  let score = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- /* Draggable, bouncing, moving-light components unchanged */
14
- AFRAME.registerComponent('draggable', {/* … */});
15
  AFRAME.registerComponent('bouncing', {/* … */});
16
  AFRAME.registerComponent('moving-light', {/* … */});
17
 
18
- function moveCamera(direction) {
19
  var rig = document.querySelector('#rig');
20
- var pos = rig.getAttribute('position');
21
- var rot = rig.getAttribute('rotation');
22
- var speed = 0.5, rSpeed = 5;
23
- switch(direction) {
24
- case 'forward': pos.z -= speed; break;
25
- case 'backward': pos.z += speed; break;
26
- case 'left': pos.x -= speed; break;
27
- case 'right': pos.x += speed; break;
28
- case 'up': pos.y += speed; break;
29
- case 'down': pos.y -= speed; break;
30
- case 'reset': pos = {x:0,y:1.6,z:0}; rot = {x:0,y:0,z:0}; break;
31
- case 'rotateY+': rot.y += rSpeed; break;
32
- case 'rotateY-': rot.y -= rSpeed; break;
33
- case 'rotateZ+': rot.z += rSpeed; break;
34
- case 'rotateZ-': rot.z -= rSpeed; break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  rig.setAttribute('position', pos);
37
  rig.setAttribute('rotation', rot);
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  function fireRaycast() {
41
  var cam = document.querySelector('[camera]');
42
  var dir = new THREE.Vector3(); cam.object3D.getWorldDirection(dir);
@@ -56,16 +174,21 @@ def load_aframe_and_extras():
56
 
57
  document.addEventListener('keydown', e => {
58
  switch(e.key.toLowerCase()){
59
- case 'w': moveCamera('forward'); break;
60
- case 'x': moveCamera('backward'); break;
61
- case 'a': moveCamera('left'); break;
62
- case 'd': moveCamera('right'); break;
63
- case 's': moveCamera('reset'); break;
64
- case 'q': moveCamera('rotateY+'); break;
65
- case 'e': moveCamera('rotateY-'); break;
66
- case 'z': moveCamera('rotateZ+'); break;
67
- case 'c': moveCamera('rotateZ-'); break;
68
- case ' ': fireRaycast(); break;
 
 
 
 
 
69
  }
70
  });
71
  </script>
@@ -76,7 +199,6 @@ def encode_file(path):
76
  with open(path,'rb') as f: return base64.b64encode(f.read()).decode()
77
 
78
  def create_aframe_entity(stem, ext, pos):
79
- # static random Y rotation, scale fills 1×1 tile
80
  ry = random.uniform(0,360)
81
  if ext == 'obj':
82
  return (f'<a-entity obj-model="obj:#{stem}" '
@@ -90,7 +212,7 @@ def create_aframe_entity(stem, ext, pos):
90
 
91
  @st.cache_data
92
  def generate_tilemap(files, dirpath, gw=8, gh=8):
93
- img_exts = ['webp','png']
94
  model_exts = ['obj','glb','gltf']
95
  vid_exts = ['mp4']
96
 
@@ -114,52 +236,64 @@ def generate_tilemap(files, dirpath, gw=8, gh=8):
114
  assets += "</a-assets>"
115
 
116
  entities = ""
117
- sx=-gw/2; sz=-gh/2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  for i in range(gw):
119
  for j in range(gh):
120
  x,y,z = sx+i,0,sz+j
121
- # ground image
122
- if imgs:
123
- img=random.choice(imgs); s=Path(img).stem
124
- entities += (f'<a-plane src="#{s}" width="1" height="1" '
125
- f'rotation="-90 0 0" position="{x} 0.01 {z}"></a-plane>')
126
- # model
127
  if models:
128
- m=random.choice(models); ext=m.split('.')[-1]; s=Path(m).stem
129
- entities += create_aframe_entity(s,ext,f"{x} 0.5 {z}")
130
- # video
131
- if vids:
132
- v=random.choice(vids); s=Path(v).stem
133
- entities += (f'<a-video src="#{s}" width="1" height="1" '
134
- f'rotation="-90 0 0" position="{x} 0.2 {z}" '
135
- 'class="raycastable" draggable></a-video>')
136
  return assets, entities
137
 
138
  def main():
139
  st.set_page_config(layout="wide")
140
  with st.sidebar:
141
- st.markdown("### ⬆️ Upload 3D / media files")
142
- ups = st.file_uploader("Add files:", accept_multiple_files=True)
143
- st.markdown("### 🎮 Camera Buttons")
144
- # 3×3 grid of buttons for qwe/asd/zxc
145
- rows = [
146
- [('Q','rotateY+'), ('W','forward'), ('E','rotateY-')],
147
- [('A','left'), ('S','reset'), ('D','right')],
148
- [('Z','rotateZ+'),('X','backward'),('C','rotateZ-')]
149
- ]
150
- for row in rows:
151
- cols = st.columns(3)
152
- for (btn,cmd),col in zip(row, cols):
153
- col.button(btn, on_click=lambda c=cmd: st.session_state.update({'camera_move':c}))
154
- st.markdown("### 🗺️ Grid is fixed at 8×8")
155
- st.markdown("### 📁 Directory")
 
 
 
156
  directory = st.text_input("Path:", ".", key="dir")
 
 
 
 
 
 
 
157
 
158
  if not os.path.isdir(directory):
159
  st.sidebar.error("Invalid directory")
160
  return
161
 
162
- types = ['obj','glb','gltf','webp','png','mp4']
163
  if ups:
164
  for up in ups:
165
  ext=Path(up.name).suffix.lower()[1:]
@@ -172,23 +306,19 @@ def main():
172
 
173
  files = [f for f in os.listdir(directory) if f.split('.')[-1] in types]
174
 
175
- # spotlight height
176
  spot_h = max(8,8)*1.5
177
 
178
- # build scene
179
  scene = f"""
180
- <a-scene embedded style="height:600px; width:100%;">
181
- <a-entity id="rig" position="0 1.6 0" rotation="0 0 0">
182
- <a-camera fov="60" look-controls wasd-controls="enabled:true"
183
  cursor="rayOrigin:mouse" raycaster="objects:.raycastable">
184
  </a-camera>
185
  </a-entity>
186
  <a-sky color="#87CEEB"></a-sky>
187
- <!-- moving lights -->
188
  <a-entity moving-light="color:#FFD700; speed:0.07 0.05 0.06; bounds:4 3 4" position="2 2 -2"></a-entity>
189
  <a-entity moving-light="color:#FF6347; speed:0.06 0.08 0.05; bounds:4 3 4" position="-2 1 2"></a-entity>
190
  <a-entity moving-light="color:#00CED1; speed:0.05 0.06 0.07; bounds:4 3 4" position="0 3 0"></a-entity>
191
- <!-- top-down spotlight -->
192
  <a-entity light="type:spot; color:#FFF; intensity:1; angle:45; penumbra:0.2"
193
  position="0 {spot_h} 0" rotation="-90 0 0"></a-entity>
194
  <a-text id="score" value="Score:0" position="-1.5 2 -3" scale="0.5 0.5 0.5" color="white"></a-text>
@@ -197,19 +327,22 @@ def main():
197
  assets, ents = generate_tilemap(files, directory, 8, 8)
198
  scene += assets + ents + "</a-scene>"
199
 
200
- # apply button or key moves
201
- cmd = st.session_state.get('camera_move')
202
- if cmd:
203
- scene += f"<script>moveCamera('{cmd}');</script>"
204
- st.session_state.pop('camera_move')
 
 
 
 
205
 
206
- # loader for OBJ/glTF
207
  loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
208
 
209
  st.components.v1.html(
210
  load_aframe_and_extras() + loader + scene,
211
- height=650
212
  )
213
 
214
  if __name__ == "__main__":
215
- main()
 
9
  <script src="https://unpkg.com/[email protected]/dist/aframe-event-set-component.min.js"></script>
10
  <script>
11
  let score = 0;
12
+ let selectedEntity = null;
13
+ let velocity = {x: 0, y: 0, z: 0};
14
+ let maxSpeed = 0.5;
15
+ let accel = 0.02;
16
+
17
+ AFRAME.registerComponent('draggable', {
18
+ init: function () {
19
+ this.el.addEventListener('mousedown', this.onMouseDown.bind(this));
20
+ this.el.addEventListener('touchstart', this.onTouchStart.bind(this));
21
+ this.el.addEventListener('mouseup', this.onMouseUp.bind(this));
22
+ this.el.addEventListener('touchend', this.onTouchEnd.bind(this));
23
+ this.el.addEventListener('mousemove', this.onMouseMove.bind(this));
24
+ this.el.addEventListener('touchmove', this.onTouchMove.bind(this));
25
+ },
26
+ onMouseDown: function (evt) {
27
+ selectedEntity = this.el;
28
+ },
29
+ onTouchStart: function (evt) {
30
+ evt.preventDefault();
31
+ selectedEntity = this.el;
32
+ },
33
+ onMouseUp: function () {
34
+ selectedEntity = null;
35
+ },
36
+ onTouchEnd: function () {
37
+ selectedEntity = null;
38
+ },
39
+ onMouseMove: function (evt) {
40
+ if (selectedEntity) {
41
+ let cam = document.querySelector('[camera]');
42
+ let dir = new THREE.Vector3();
43
+ cam.object3D.getWorldDirection(dir);
44
+ let rc = new THREE.Raycaster(cam.object3D.position, dir);
45
+ let plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
46
+ let pos = new THREE.Vector3();
47
+ rc.ray.intersectPlane(plane, pos);
48
+ selectedEntity.setAttribute('position', {x: pos.x, y: 0, z: pos.z});
49
+ }
50
+ },
51
+ onTouchMove: function (evt) {
52
+ evt.preventDefault();
53
+ if (selectedEntity) {
54
+ let cam = document.querySelector('[camera]');
55
+ let dir = new THREE.Vector3();
56
+ cam.object3D.getWorldDirection(dir);
57
+ let rc = new THREE.Raycaster(cam.object3D.position, dir);
58
+ let plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
59
+ let pos = new THREE.Vector3();
60
+ rc.ray.intersectPlane(plane, pos);
61
+ selectedEntity.setAttribute('position', {x: pos.x, y: 0, z: pos.z});
62
+ }
63
+ }
64
+ });
65
 
 
 
66
  AFRAME.registerComponent('bouncing', {/* … */});
67
  AFRAME.registerComponent('moving-light', {/* … */});
68
 
69
+ function moveCamera(view) {
70
  var rig = document.querySelector('#rig');
71
+ var gw = 8, gh = 8;
72
+ var center = {x: 0, y: 0, z: 0};
73
+ var height = Math.max(gw, gh) * 1.5; // y=12 for center view
74
+ var lowHeight = 3; // y=3 for closer views
75
+ var quadrantOffset = Math.max(gw, gh) / 4; // 2 units to center on quadrants
76
+ var pos, rot;
77
+
78
+ rot = {x: -90, y: 0, z: 0}; // Always top-down view
79
+
80
+ switch(view) {
81
+ case 'center':
82
+ pos = {x: center.x, y: height, z: center.z};
83
+ break;
84
+ case 'left':
85
+ pos = {x: -quadrantOffset, y: lowHeight, z: center.z}; // Center on left side
86
+ break;
87
+ case 'right':
88
+ pos = {x: quadrantOffset, y: lowHeight, z: center.z}; // Center on right side
89
+ break;
90
+ case 'front':
91
+ pos = {x: center.x, y: lowHeight, z: -quadrantOffset}; // Center on top side
92
+ break;
93
+ case 'back':
94
+ pos = {x: center.x, y: lowHeight, z: quadrantOffset}; // Center on bottom side
95
+ break;
96
+ case 'angle1':
97
+ pos = {x: -quadrantOffset, y: lowHeight, z: -quadrantOffset}; // Top-left quadrant
98
+ break;
99
+ case 'angle2':
100
+ pos = {x: quadrantOffset, y: lowHeight, z: -quadrantOffset}; // Top-right quadrant
101
+ break;
102
+ case 'angle3':
103
+ pos = {x: -quadrantOffset, y: lowHeight, z: quadrantOffset}; // Bottom-left quadrant
104
+ break;
105
+ case 'angle4':
106
+ pos = {x: quadrantOffset, y: lowHeight, z: quadrantOffset}; // Bottom-right quadrant
107
+ break;
108
  }
109
  rig.setAttribute('position', pos);
110
  rig.setAttribute('rotation', rot);
111
  }
112
 
113
+ function flyCamera(action) {
114
+ var rig = document.querySelector('#rig');
115
+ var rot = rig.getAttribute('rotation');
116
+ var rSpeed = 2;
117
+
118
+ switch(action) {
119
+ case 'forward':
120
+ var cam = document.querySelector('[camera]');
121
+ var dir = new THREE.Vector3();
122
+ cam.object3D.getWorldDirection(dir); // Raycast direction (downward for top-down view)
123
+ var pos = rig.getAttribute('position');
124
+ pos.x += dir.x * 0.1;
125
+ pos.y += dir.y * 0.1;
126
+ pos.z += dir.z * 0.1;
127
+ rig.setAttribute('position', pos);
128
+ break;
129
+ case 'backward':
130
+ velocity.z = Math.min(velocity.z + accel, maxSpeed);
131
+ break;
132
+ case 'stop':
133
+ velocity = {x: 0, y: 0, z: 0};
134
+ moveCamera('center');
135
+ break;
136
+ case 'rollCCW':
137
+ rot.z += rSpeed;
138
+ break;
139
+ case 'rollCW':
140
+ rot.z -= rSpeed;
141
+ break;
142
+ }
143
+ rig.setAttribute('rotation', rot);
144
+ }
145
+
146
+ function updateCameraPosition() {
147
+ var rig = document.querySelector('#rig');
148
+ var pos = rig.getAttribute('position');
149
+ pos.x += velocity.x;
150
+ pos.y += velocity.y;
151
+ pos.z += velocity.z;
152
+ rig.setAttribute('position', pos);
153
+ requestAnimationFrame(updateCameraPosition);
154
+ }
155
+
156
+ requestAnimationFrame(updateCameraPosition);
157
+
158
  function fireRaycast() {
159
  var cam = document.querySelector('[camera]');
160
  var dir = new THREE.Vector3(); cam.object3D.getWorldDirection(dir);
 
174
 
175
  document.addEventListener('keydown', e => {
176
  switch(e.key.toLowerCase()){
177
+ case '1': moveCamera('center'); break;
178
+ case '2': moveCamera('left'); break;
179
+ case '3': moveCamera('right'); break;
180
+ case '4': moveCamera('front'); break;
181
+ case '5': moveCamera('back'); break;
182
+ case '6': moveCamera('angle1'); break;
183
+ case '7': moveCamera('angle2'); break;
184
+ case '8': moveCamera('angle3'); break;
185
+ case '9': moveCamera('angle4'); break;
186
+ case 'w': flyCamera('forward'); break;
187
+ case 'x': flyCamera('backward'); break;
188
+ case 's': flyCamera('stop'); break;
189
+ case 'q': flyCamera('rollCCW'); break;
190
+ case 'e': flyCamera('rollCW'); break;
191
+ case ' ': fireRaycast(); break;
192
  }
193
  });
194
  </script>
 
199
  with open(path,'rb') as f: return base64.b64encode(f.read()).decode()
200
 
201
  def create_aframe_entity(stem, ext, pos):
 
202
  ry = random.uniform(0,360)
203
  if ext == 'obj':
204
  return (f'<a-entity obj-model="obj:#{stem}" '
 
212
 
213
  @st.cache_data
214
  def generate_tilemap(files, dirpath, gw=8, gh=8):
215
+ img_exts = ['webp','png','jpeg','jpg']
216
  model_exts = ['obj','glb','gltf']
217
  vid_exts = ['mp4']
218
 
 
236
  assets += "</a-assets>"
237
 
238
  entities = ""
239
+ if vids:
240
+ v = vids[0]; s = Path(v).stem
241
+ entities += (f'<a-video src="#{s}" width="{gw}" height="{gh}" '
242
+ f'rotation="-90 0 0" position="0 0.05 0" '
243
+ 'loop autoplay></a-video>')
244
+ else:
245
+ sx = -gw/2; sz = -gh/2
246
+ for i in range(gw):
247
+ for j in range(gh):
248
+ x,y,z = sx+i,0,sz+j
249
+ if imgs:
250
+ img = random.choice(imgs); s = Path(img).stem
251
+ entities += (f'<a-plane src="#{s}" width="1" height="1" '
252
+ f'rotation="-90 0 0" position="{x} 0 {z}"></a-plane>')
253
+ sx = -gw/2; sz = -gh/2
254
  for i in range(gw):
255
  for j in range(gh):
256
  x,y,z = sx+i,0,sz+j
 
 
 
 
 
 
257
  if models:
258
+ m = random.choice(models); ext = m.split('.')[-1]; s = Path(m).stem
259
+ entities += create_aframe_entity(s, ext, f"{x} 0 {z}")
 
 
 
 
 
 
260
  return assets, entities
261
 
262
  def main():
263
  st.set_page_config(layout="wide")
264
  with st.sidebar:
265
+ st.markdown("### 🧭 Camera Views")
266
+ st.markdown("**Select Quadrant** 📷")
267
+ cols = st.columns(3)
268
+ cols[0].button("↖️ Top-Left", on_click=lambda: st.session_state.update({'camera_view': 'angle1'}))
269
+ cols[1].button("⬆️ Top", on_click=lambda: st.session_state.update({'camera_view': 'front'}))
270
+ cols[2].button("↗️ Top-Right", on_click=lambda: st.session_state.update({'camera_view': 'angle2'}))
271
+ cols = st.columns(3)
272
+ cols[0].button("⬅️ Left", on_click=lambda: st.session_state.update({'camera_view': 'left'}))
273
+ cols[1].button("🔳 Center", on_click=lambda: st.session_state.update({'camera_view': 'center'}))
274
+ cols[2].button("➡️ Right", on_click=lambda: st.session_state.update({'camera_view': 'right'}))
275
+ cols = st.columns(3)
276
+ cols[0].button("↙️ Bottom-Left", on_click=lambda: st.session_state.update({'camera_view': 'angle3'}))
277
+ cols[1].button("⬇️ Bottom", on_click=lambda: st.session_state.update({'camera_view': 'back'}))
278
+ cols[2].button("↘️ Bottom-Right", on_click=lambda: st.session_state.update({'camera_view': 'angle4'}))
279
+
280
+ st.markdown("### ➕ Add Media Files")
281
+ ups = st.file_uploader("Add files (png, jpeg, obj, glb, mp4, etc.):", accept_multiple_files=True)
282
+ st.markdown("### 📋 Uploaded Model Files")
283
  directory = st.text_input("Path:", ".", key="dir")
284
+ if os.path.isdir(directory):
285
+ files = [f for f in os.listdir(directory) if f.split('.')[-1] in ['obj', 'glb', 'gltf']]
286
+ if files:
287
+ for i, f in enumerate(files, 1):
288
+ st.markdown(f"{i}. {f}")
289
+ else:
290
+ st.markdown("No model files found.")
291
 
292
  if not os.path.isdir(directory):
293
  st.sidebar.error("Invalid directory")
294
  return
295
 
296
+ types = ['obj','glb','gltf','webp','png','jpeg','jpg','mp4']
297
  if ups:
298
  for up in ups:
299
  ext=Path(up.name).suffix.lower()[1:]
 
306
 
307
  files = [f for f in os.listdir(directory) if f.split('.')[-1] in types]
308
 
 
309
  spot_h = max(8,8)*1.5
310
 
 
311
  scene = f"""
312
+ <a-scene embedded style="height:100vh; width:100vw; position:fixed; top:0; left:0;">
313
+ <a-entity id="rig" position="0 12 0" rotation="-90 0 0">
314
+ <a-camera fov="60" look-controls wasd-controls="enabled:false"
315
  cursor="rayOrigin:mouse" raycaster="objects:.raycastable">
316
  </a-camera>
317
  </a-entity>
318
  <a-sky color="#87CEEB"></a-sky>
 
319
  <a-entity moving-light="color:#FFD700; speed:0.07 0.05 0.06; bounds:4 3 4" position="2 2 -2"></a-entity>
320
  <a-entity moving-light="color:#FF6347; speed:0.06 0.08 0.05; bounds:4 3 4" position="-2 1 2"></a-entity>
321
  <a-entity moving-light="color:#00CED1; speed:0.05 0.06 0.07; bounds:4 3 4" position="0 3 0"></a-entity>
 
322
  <a-entity light="type:spot; color:#FFF; intensity:1; angle:45; penumbra:0.2"
323
  position="0 {spot_h} 0" rotation="-90 0 0"></a-entity>
324
  <a-text id="score" value="Score:0" position="-1.5 2 -3" scale="0.5 0.5 0.5" color="white"></a-text>
 
327
  assets, ents = generate_tilemap(files, directory, 8, 8)
328
  scene += assets + ents + "</a-scene>"
329
 
330
+ view_cmd = st.session_state.get('camera_view', 'center')
331
+ if view_cmd:
332
+ scene += f"<script>moveCamera('{view_cmd}');</script>"
333
+ st.session_state.pop('camera_view', None)
334
+
335
+ fly_cmd = st.session_state.get('fly_action')
336
+ if fly_cmd:
337
+ scene += f"<script>flyCamera('{fly_cmd}');</script>"
338
+ st.session_state.pop('fly_action', None)
339
 
 
340
  loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
341
 
342
  st.components.v1.html(
343
  load_aframe_and_extras() + loader + scene,
344
+ height=1000
345
  )
346
 
347
  if __name__ == "__main__":
348
+ main()