awacke1 commited on
Commit
4322098
·
verified ·
1 Parent(s): 1d5ce9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -70
app.py CHANGED
@@ -9,31 +9,105 @@ 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
- case 'zoomIn': rig.object3D.scale.multiplyScalar(0.9); break;
36
- case 'zoomOut': rig.object3D.scale.multiplyScalar(1.1); break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
  rig.setAttribute('position', pos);
39
  rig.setAttribute('rotation', rot);
@@ -58,18 +132,16 @@ def load_aframe_and_extras():
58
 
59
  document.addEventListener('keydown', e => {
60
  switch(e.key.toLowerCase()){
61
- case 'arrowup': moveCamera('forward'); break;
62
- case 'arrowdown': moveCamera('backward'); break;
63
- case 'arrowleft': moveCamera('left'); break;
64
- case 'arrowright': moveCamera('right'); break;
65
- case 'r': moveCamera('reset'); break;
66
- case 'q': moveCamera('rotateY+'); break;
67
- case 'e': moveCamera('rotateY-'); break;
68
- case 'z': moveCamera('rotateZ+'); break;
69
- case 'c': moveCamera('rotateZ-'); break;
70
- case 'pageup': moveCamera('zoomIn'); break;
71
- case 'pagedown': moveCamera('zoomOut'); break;
72
- case ' ': fireRaycast(); break;
73
  }
74
  });
75
  </script>
@@ -93,7 +165,7 @@ def create_aframe_entity(stem, ext, pos):
93
 
94
  @st.cache_data
95
  def generate_tilemap(files, dirpath, gw=8, gh=8):
96
- img_exts = ['webp','png']
97
  model_exts = ['obj','glb','gltf']
98
  vid_exts = ['mp4']
99
 
@@ -124,49 +196,37 @@ def generate_tilemap(files, dirpath, gw=8, gh=8):
124
  if imgs:
125
  img=random.choice(imgs); s=Path(img).stem
126
  entities += (f'<a-plane src="#{s}" width="1" height="1" '
127
- f'rotation="-90 0 0" position="{x} 0.01 {z}"></a-plane>')
128
  if models:
129
  m=random.choice(models); ext=m.split('.')[-1]; s=Path(m).stem
130
- entities += create_aframe_entity(s,ext,f"{x} 0.5 {z}")
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("### 🧭 Navigation Controls")
142
- # Pan the View
143
- st.markdown("**Pan the View** ⬅️➡️")
144
- cols = st.columns(4)
145
- cols[0].button("⬅️", on_click=lambda: st.session_state.update({'camera_move': 'left'}))
146
- cols[1].button("➡️", on_click=lambda: st.session_state.update({'camera_move': 'right'}))
147
- cols[2].button("⬆️", on_click=lambda: st.session_state.update({'camera_move': 'forward'}))
148
- cols[3].button("⬇️", on_click=lambda: st.session_state.update({'camera_move': 'backward'}))
149
-
150
- # Rotate the 3D Scene
151
- st.markdown("**Rotate the 3D Scene** 🔄")
152
- cols = st.columns(4)
153
- cols[0].button("⬅️ Rotate Y+", on_click=lambda: st.session_state.update({'camera_move': 'rotateY+'}))
154
- cols[1].button("➡️ Rotate Y-", on_click=lambda: st.session_state.update({'camera_move': 'rotateY-'}))
155
- cols[2].button("↖️ Rotate Z+", on_click=lambda: st.session_state.update({'camera_move': 'rotateZ+'}))
156
- cols[3].button("↘️ Rotate Z-", on_click=lambda: st.session_state.update({'camera_move': 'rotateZ-'}))
157
-
158
- # Zoom Controls
159
- st.markdown("**Zoom** 🔎")
160
- cols = st.columns(2)
161
- cols[0].button("➕ Zoom In", on_click=lambda: st.session_state.update({'camera_move': 'zoomIn'}))
162
- cols[1].button("➖ Zoom Out", on_click=lambda: st.session_state.update({'camera_move': 'zoomOut'}))
163
-
164
- # Reset View
165
- st.markdown("**Reset View** 🔄")
166
- st.button("🔄 Reset", on_click=lambda: st.session_state.update({'camera_move': 'reset'}))
167
 
168
  st.markdown("### ➕ Add Media Files")
169
- ups = st.file_uploader("Add files (png, obj, glb, etc.):", accept_multiple_files=True)
170
  st.markdown("### 📋 Uploaded Model Files")
171
  directory = st.text_input("Path:", ".", key="dir")
172
  if os.path.isdir(directory):
@@ -181,7 +241,7 @@ def main():
181
  st.sidebar.error("Invalid directory")
182
  return
183
 
184
- types = ['obj','glb','gltf','webp','png','mp4']
185
  if ups:
186
  for up in ups:
187
  ext=Path(up.name).suffix.lower()[1:]
@@ -197,9 +257,9 @@ def main():
197
  spot_h = max(8,8)*1.5
198
 
199
  scene = f"""
200
- <a-scene embedded style="height:600px; width:100%;">
201
- <a-entity id="rig" position="0 1.6 0" rotation="0 0 0">
202
- <a-camera fov="60" look-controls wasd-controls="enabled:true"
203
  cursor="rayOrigin:mouse" raycaster="objects:.raycastable">
204
  </a-camera>
205
  </a-entity>
@@ -215,16 +275,16 @@ def main():
215
  assets, ents = generate_tilemap(files, directory, 8, 8)
216
  scene += assets + ents + "</a-scene>"
217
 
218
- cmd = st.session_state.get('camera_move')
219
  if cmd:
220
  scene += f"<script>moveCamera('{cmd}');</script>"
221
- st.session_state.pop('camera_move')
222
 
223
  loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
224
 
225
  st.components.v1.html(
226
  load_aframe_and_extras() + loader + scene,
227
- height=650
228
  )
229
 
230
  if __name__ == "__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
+
14
+ AFRAME.registerComponent('draggable', {
15
+ init: function () {
16
+ this.el.addEventListener('mousedown', this.onMouseDown.bind(this));
17
+ this.el.addEventListener('touchstart', this.onTouchStart.bind(this));
18
+ this.el.addEventListener('mouseup', this.onMouseUp.bind(this));
19
+ this.el.addEventListener('touchend', this.onTouchEnd.bind(this));
20
+ this.el.addEventListener('mousemove', this.onMouseMove.bind(this));
21
+ this.el.addEventListener('touchmove', this.onTouchMove.bind(this));
22
+ },
23
+ onMouseDown: function (evt) {
24
+ selectedEntity = this.el;
25
+ },
26
+ onTouchStart: function (evt) {
27
+ evt.preventDefault();
28
+ selectedEntity = this.el;
29
+ },
30
+ onMouseUp: function () {
31
+ selectedEntity = null;
32
+ },
33
+ onTouchEnd: function () {
34
+ selectedEntity = null;
35
+ },
36
+ onMouseMove: function (evt) {
37
+ if (selectedEntity) {
38
+ let cam = document.querySelector('[camera]');
39
+ let dir = new THREE.Vector3();
40
+ cam.object3D.getWorldDirection(dir);
41
+ let rc = new THREE.Raycaster(cam.object3D.position, dir);
42
+ let plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
43
+ let pos = new THREE.Vector3();
44
+ rc.ray.intersectPlane(plane, pos);
45
+ selectedEntity.setAttribute('position', {x: pos.x, y: 0, z: pos.z});
46
+ }
47
+ },
48
+ onTouchMove: function (evt) {
49
+ evt.preventDefault();
50
+ if (selectedEntity) {
51
+ let cam = document.querySelector('[camera]');
52
+ let dir = new THREE.Vector3();
53
+ cam.object3D.getWorldDirection(dir);
54
+ let rc = new THREE.Raycaster(cam.object3D.position, dir);
55
+ let plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
56
+ let pos = new THREE.Vector3();
57
+ rc.ray.intersectPlane(plane, pos);
58
+ selectedEntity.setAttribute('position', {x: pos.x, y: 0, z: pos.z});
59
+ }
60
+ }
61
+ });
62
 
 
 
63
  AFRAME.registerComponent('bouncing', {/* … */});
64
  AFRAME.registerComponent('moving-light', {/* … */});
65
 
66
+ function moveCamera(view) {
67
  var rig = document.querySelector('#rig');
68
+ var gw = 8, gh = 8;
69
+ var centerX = 0, centerZ = 0;
70
+ var height = Math.max(gw, gh) * 1.5;
71
+ var distance = Math.max(gw, gh) * 1.2;
72
+ var pos, rot;
73
+
74
+ switch(view) {
75
+ case 'top':
76
+ pos = {x: centerX, y: height, z: centerZ};
77
+ rot = {x: -90, y: 0, z: 0};
78
+ break;
79
+ case 'left':
80
+ pos = {x: -distance, y: height / 2, z: centerZ};
81
+ rot = {x: 0, y: 90, z: 0};
82
+ break;
83
+ case 'right':
84
+ pos = {x: distance, y: height / 2, z: centerZ};
85
+ rot = {x: 0, y: -90, z: 0};
86
+ break;
87
+ case 'front':
88
+ pos = {x: centerX, y: height / 2, z: -distance};
89
+ rot = {x: 0, y: 0, z: 0};
90
+ break;
91
+ case 'back':
92
+ pos = {x: centerX, y: height / 2, z: distance};
93
+ rot = {x: 0, y: 180, z: 0};
94
+ break;
95
+ case 'angle1':
96
+ pos = {x: -distance * 0.7, y: height, z: -distance * 0.7};
97
+ rot = {x: -45, y: 45, z: 0};
98
+ break;
99
+ case 'angle2':
100
+ pos = {x: distance * 0.7, y: height, z: -distance * 0.7};
101
+ rot = {x: -45, y: -45, z: 0};
102
+ break;
103
+ case 'angle3':
104
+ pos = {x: -distance * 0.7, y: height, z: distance * 0.7};
105
+ rot = {x: -45, y: 135, z: 0};
106
+ break;
107
+ case 'angle4':
108
+ pos = {x: distance * 0.7, y: height, z: distance * 0.7};
109
+ rot = {x: -45, y: -135, z: 0};
110
+ break;
111
  }
112
  rig.setAttribute('position', pos);
113
  rig.setAttribute('rotation', rot);
 
132
 
133
  document.addEventListener('keydown', e => {
134
  switch(e.key.toLowerCase()){
135
+ case '1': moveCamera('top'); break;
136
+ case '2': moveCamera('left'); break;
137
+ case '3': moveCamera('right'); break;
138
+ case '4': moveCamera('front'); break;
139
+ case '5': moveCamera('back'); break;
140
+ case '6': moveCamera('angle1'); break;
141
+ case '7': moveCamera('angle2'); break;
142
+ case '8': moveCamera('angle3'); break;
143
+ case '9': moveCamera('angle4'); break;
144
+ case ' ': fireRaycast(); break;
 
 
145
  }
146
  });
147
  </script>
 
165
 
166
  @st.cache_data
167
  def generate_tilemap(files, dirpath, gw=8, gh=8):
168
+ img_exts = ['webp','png','jpeg','jpg']
169
  model_exts = ['obj','glb','gltf']
170
  vid_exts = ['mp4']
171
 
 
196
  if imgs:
197
  img=random.choice(imgs); s=Path(img).stem
198
  entities += (f'<a-plane src="#{s}" width="1" height="1" '
199
+ f'rotation="-90 0 0" position="{x} 0 {z}"></a-plane>')
200
  if models:
201
  m=random.choice(models); ext=m.split('.')[-1]; s=Path(m).stem
202
+ entities += create_aframe_entity(s,ext,f"{x} 0 {z}")
203
  if vids:
204
  v=random.choice(vids); s=Path(v).stem
205
  entities += (f'<a-video src="#{s}" width="1" height="1" '
206
+ f'rotation="-90 0 0" position="{x} 0.1 {z}" '
207
  'class="raycastable" draggable></a-video>')
208
  return assets, entities
209
 
210
  def main():
211
  st.set_page_config(layout="wide")
212
  with st.sidebar:
213
+ st.markdown("### 🧭 Camera Views")
214
+ st.markdown("**Select View** 📷")
215
+ cols = st.columns(3)
216
+ cols[0].button("🔝 Top", on_click=lambda: st.session_state.update({'camera_view': 'top'}))
217
+ cols[1].button("⬅️ Left", on_click=lambda: st.session_state.update({'camera_view': 'left'}))
218
+ cols[2].button("➡️ Right", on_click=lambda: st.session_state.update({'camera_view': 'right'}))
219
+ cols = st.columns(3)
220
+ cols[0].button("⬆️ Front", on_click=lambda: st.session_state.update({'camera_view': 'front'}))
221
+ cols[1].button("⬇️ Back", on_click=lambda: st.session_state.update({'camera_view': 'back'}))
222
+ cols[2].button("↖️ Angle 1", on_click=lambda: st.session_state.update({'camera_view': 'angle1'}))
223
+ cols = st.columns(3)
224
+ cols[0].button("↗️ Angle 2", on_click=lambda: st.session_state.update({'camera_view': 'angle2'}))
225
+ cols[1].button("↙️ Angle 3", on_click=lambda: st.session_state.update({'camera_view': 'angle3'}))
226
+ cols[2].button("↘️ Angle 4", on_click=lambda: st.session_state.update({'camera_view': 'angle4'}))
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
  st.markdown("### ➕ Add Media Files")
229
+ ups = st.file_uploader("Add files (png, jpeg, obj, glb, mp4, etc.):", accept_multiple_files=True)
230
  st.markdown("### 📋 Uploaded Model Files")
231
  directory = st.text_input("Path:", ".", key="dir")
232
  if os.path.isdir(directory):
 
241
  st.sidebar.error("Invalid directory")
242
  return
243
 
244
+ types = ['obj','glb','gltf','webp','png','jpeg','jpg','mp4']
245
  if ups:
246
  for up in ups:
247
  ext=Path(up.name).suffix.lower()[1:]
 
257
  spot_h = max(8,8)*1.5
258
 
259
  scene = f"""
260
+ <a-scene embedded style="height:100vh; width:100vw; position:fixed; top:0; left:0;">
261
+ <a-entity id="rig" position="0 12 0" rotation="-90 0 0">
262
+ <a-camera fov="60" look-controls wasd-controls="enabled:false"
263
  cursor="rayOrigin:mouse" raycaster="objects:.raycastable">
264
  </a-camera>
265
  </a-entity>
 
275
  assets, ents = generate_tilemap(files, directory, 8, 8)
276
  scene += assets + ents + "</a-scene>"
277
 
278
+ cmd = st.session_state.get('camera_view', 'top')
279
  if cmd:
280
  scene += f"<script>moveCamera('{cmd}');</script>"
281
+ st.session_state.pop('camera_view', None)
282
 
283
  loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
284
 
285
  st.components.v1.html(
286
  load_aframe_and_extras() + loader + scene,
287
+ height=1000
288
  )
289
 
290
  if __name__ == "__main__":