Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -11,6 +11,7 @@ def load_aframe_and_extras():
|
|
11 |
<script>
|
12 |
let score = 0;
|
13 |
let selectedEntity = null;
|
|
|
14 |
AFRAME.registerComponent('draggable', {
|
15 |
init: function () {
|
16 |
this.el.addEventListener('mousedown', this.onMouseDown.bind(this));
|
@@ -59,15 +60,18 @@ def load_aframe_and_extras():
|
|
59 |
}
|
60 |
}
|
61 |
});
|
|
|
62 |
AFRAME.registerComponent('bouncing', {/* … */});
|
63 |
AFRAME.registerComponent('moving-light', {/* … */});
|
|
|
64 |
function moveCamera(view) {
|
65 |
var rig = document.querySelector('#rig');
|
66 |
var gw = 8, gh = 8;
|
67 |
var center = {x: 0, y: 0, z: 0};
|
68 |
var height = Math.max(gw, gh) * 1.5;
|
69 |
-
var distance = Math.max(gw, gh) *
|
70 |
var pos;
|
|
|
71 |
switch(view) {
|
72 |
case 'top':
|
73 |
pos = {x: center.x, y: height, z: center.z};
|
@@ -75,47 +79,89 @@ def load_aframe_and_extras():
|
|
75 |
rig.setAttribute('rotation', {x: -90, y: 0, z: 0});
|
76 |
break;
|
77 |
case 'left':
|
78 |
-
pos = {x: -distance, y: height
|
79 |
rig.setAttribute('position', pos);
|
80 |
rig.setAttribute('look-at', center);
|
81 |
break;
|
82 |
case 'right':
|
83 |
-
pos = {x: distance, y: height
|
84 |
rig.setAttribute('position', pos);
|
85 |
rig.setAttribute('look-at', center);
|
86 |
break;
|
87 |
case 'front':
|
88 |
-
pos = {x: center.x, y: height
|
89 |
rig.setAttribute('position', pos);
|
90 |
rig.setAttribute('look-at', center);
|
91 |
break;
|
92 |
case 'back':
|
93 |
-
pos = {x: center.x, y: height
|
94 |
rig.setAttribute('position', pos);
|
95 |
rig.setAttribute('look-at', center);
|
96 |
break;
|
97 |
case 'angle1':
|
98 |
-
pos = {x: -distance
|
99 |
rig.setAttribute('position', pos);
|
100 |
rig.setAttribute('look-at', center);
|
101 |
break;
|
102 |
case 'angle2':
|
103 |
-
pos = {x: distance
|
104 |
rig.setAttribute('position', pos);
|
105 |
rig.setAttribute('look-at', center);
|
106 |
break;
|
107 |
case 'angle3':
|
108 |
-
pos = {x: -distance
|
109 |
rig.setAttribute('position', pos);
|
110 |
rig.setAttribute('look-at', center);
|
111 |
break;
|
112 |
case 'angle4':
|
113 |
-
pos = {x: distance
|
114 |
rig.setAttribute('position', pos);
|
115 |
rig.setAttribute('look-at', center);
|
116 |
break;
|
117 |
}
|
118 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
function fireRaycast() {
|
120 |
var cam = document.querySelector('[camera]');
|
121 |
var dir = new THREE.Vector3(); cam.object3D.getWorldDirection(dir);
|
@@ -132,6 +178,7 @@ def load_aframe_and_extras():
|
|
132 |
}
|
133 |
}
|
134 |
}
|
|
|
135 |
document.addEventListener('keydown', e => {
|
136 |
switch(e.key.toLowerCase()){
|
137 |
case '1': moveCamera('top'); break;
|
@@ -143,7 +190,14 @@ def load_aframe_and_extras():
|
|
143 |
case '7': moveCamera('angle2'); break;
|
144 |
case '8': moveCamera('angle3'); break;
|
145 |
case '9': moveCamera('angle4'); break;
|
146 |
-
case '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
}
|
148 |
});
|
149 |
</script>
|
@@ -191,22 +245,30 @@ def generate_tilemap(files, dirpath, gw=8, gh=8):
|
|
191 |
assets += "</a-assets>"
|
192 |
|
193 |
entities = ""
|
194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
for i in range(gw):
|
196 |
for j in range(gh):
|
197 |
x,y,z = sx+i,0,sz+j
|
198 |
-
if imgs:
|
199 |
-
img=random.choice(imgs); s=Path(img).stem
|
200 |
-
entities += (f'<a-plane src="#{s}" width="1" height="1" '
|
201 |
-
f'rotation="-90 0 0" position="{x} 0 {z}"></a-plane>')
|
202 |
if models:
|
203 |
-
m=random.choice(models); ext=m.split('.')[-1]; s=Path(m).stem
|
204 |
-
entities += create_aframe_entity(s,ext,f"{x} 0 {z}")
|
205 |
-
if vids:
|
206 |
-
v=random.choice(vids); s=Path(v).stem
|
207 |
-
entities += (f'<a-video src="#{s}" width="1" height="1" '
|
208 |
-
f'rotation="-90 0 0" position="{x} 0.1 {z}" '
|
209 |
-
'class="raycastable" draggable></a-video>')
|
210 |
return assets, entities
|
211 |
|
212 |
def main():
|
@@ -227,6 +289,19 @@ def main():
|
|
227 |
cols[1].button("↙️ Angle 3", on_click=lambda: st.session_state.update({'camera_view': 'angle3'}))
|
228 |
cols[2].button("↘️ Angle 4", on_click=lambda: st.session_state.update({'camera_view': 'angle4'}))
|
229 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
st.markdown("### ➕ Add Media Files")
|
231 |
ups = st.file_uploader("Add files (png, jpeg, obj, glb, mp4, etc.):", accept_multiple_files=True)
|
232 |
st.markdown("### 📋 Uploaded Model Files")
|
@@ -277,11 +352,16 @@ def main():
|
|
277 |
assets, ents = generate_tilemap(files, directory, 8, 8)
|
278 |
scene += assets + ents + "</a-scene>"
|
279 |
|
280 |
-
|
281 |
-
if
|
282 |
-
scene += f"<script>moveCamera('{
|
283 |
st.session_state.pop('camera_view', None)
|
284 |
|
|
|
|
|
|
|
|
|
|
|
285 |
loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
|
286 |
|
287 |
st.components.v1.html(
|
|
|
11 |
<script>
|
12 |
let score = 0;
|
13 |
let selectedEntity = null;
|
14 |
+
|
15 |
AFRAME.registerComponent('draggable', {
|
16 |
init: function () {
|
17 |
this.el.addEventListener('mousedown', this.onMouseDown.bind(this));
|
|
|
60 |
}
|
61 |
}
|
62 |
});
|
63 |
+
|
64 |
AFRAME.registerComponent('bouncing', {/* … */});
|
65 |
AFRAME.registerComponent('moving-light', {/* … */});
|
66 |
+
|
67 |
function moveCamera(view) {
|
68 |
var rig = document.querySelector('#rig');
|
69 |
var gw = 8, gh = 8;
|
70 |
var center = {x: 0, y: 0, z: 0};
|
71 |
var height = Math.max(gw, gh) * 1.5;
|
72 |
+
var distance = Math.max(gw, gh) * 2; // Further increased distance to ensure the entire tilemap is in view
|
73 |
var pos;
|
74 |
+
|
75 |
switch(view) {
|
76 |
case 'top':
|
77 |
pos = {x: center.x, y: height, z: center.z};
|
|
|
79 |
rig.setAttribute('rotation', {x: -90, y: 0, z: 0});
|
80 |
break;
|
81 |
case 'left':
|
82 |
+
pos = {x: -distance, y: height, z: center.z};
|
83 |
rig.setAttribute('position', pos);
|
84 |
rig.setAttribute('look-at', center);
|
85 |
break;
|
86 |
case 'right':
|
87 |
+
pos = {x: distance, y: height, z: center.z};
|
88 |
rig.setAttribute('position', pos);
|
89 |
rig.setAttribute('look-at', center);
|
90 |
break;
|
91 |
case 'front':
|
92 |
+
pos = {x: center.x, y: height, z: -distance};
|
93 |
rig.setAttribute('position', pos);
|
94 |
rig.setAttribute('look-at', center);
|
95 |
break;
|
96 |
case 'back':
|
97 |
+
pos = {x: center.x, y: height, z: distance};
|
98 |
rig.setAttribute('position', pos);
|
99 |
rig.setAttribute('look-at', center);
|
100 |
break;
|
101 |
case 'angle1':
|
102 |
+
pos = {x: -distance, y: height, z: -distance};
|
103 |
rig.setAttribute('position', pos);
|
104 |
rig.setAttribute('look-at', center);
|
105 |
break;
|
106 |
case 'angle2':
|
107 |
+
pos = {x: distance, y: height, z: -distance};
|
108 |
rig.setAttribute('position', pos);
|
109 |
rig.setAttribute('look-at', center);
|
110 |
break;
|
111 |
case 'angle3':
|
112 |
+
pos = {x: -distance, y: height, z: distance};
|
113 |
rig.setAttribute('position', pos);
|
114 |
rig.setAttribute('look-at', center);
|
115 |
break;
|
116 |
case 'angle4':
|
117 |
+
pos = {x: distance, y: height, z: distance};
|
118 |
rig.setAttribute('position', pos);
|
119 |
rig.setAttribute('look-at', center);
|
120 |
break;
|
121 |
}
|
122 |
}
|
123 |
+
|
124 |
+
function flyCamera(action) {
|
125 |
+
var rig = document.querySelector('#rig');
|
126 |
+
var pos = rig.getAttribute('position');
|
127 |
+
var rot = rig.getAttribute('rotation');
|
128 |
+
var speed = 0.1, rSpeed = 2;
|
129 |
+
|
130 |
+
switch(action) {
|
131 |
+
case 'forward':
|
132 |
+
var dir = new THREE.Vector3(0, 0, -1);
|
133 |
+
dir.applyQuaternion(rig.object3D.quaternion);
|
134 |
+
pos.x += dir.x * speed;
|
135 |
+
pos.y += dir.y * speed;
|
136 |
+
pos.z += dir.z * speed;
|
137 |
+
break;
|
138 |
+
case 'backward':
|
139 |
+
var dir = new THREE.Vector3(0, 0, 1);
|
140 |
+
dir.applyQuaternion(rig.object3D.quaternion);
|
141 |
+
pos.x += dir.x * speed;
|
142 |
+
pos.y += dir.y * speed;
|
143 |
+
pos.z += dir.z * speed;
|
144 |
+
break;
|
145 |
+
case 'panLeft':
|
146 |
+
rot.y += rSpeed;
|
147 |
+
break;
|
148 |
+
case 'panRight':
|
149 |
+
rot.y -= rSpeed;
|
150 |
+
break;
|
151 |
+
case 'rotateLeft':
|
152 |
+
rot.y += rSpeed;
|
153 |
+
break;
|
154 |
+
case 'rotateRight':
|
155 |
+
rot.y -= rSpeed;
|
156 |
+
break;
|
157 |
+
case 'reset':
|
158 |
+
moveCamera('top');
|
159 |
+
return;
|
160 |
+
}
|
161 |
+
rig.setAttribute('position', pos);
|
162 |
+
rig.setAttribute('rotation', rot);
|
163 |
+
}
|
164 |
+
|
165 |
function fireRaycast() {
|
166 |
var cam = document.querySelector('[camera]');
|
167 |
var dir = new THREE.Vector3(); cam.object3D.getWorldDirection(dir);
|
|
|
178 |
}
|
179 |
}
|
180 |
}
|
181 |
+
|
182 |
document.addEventListener('keydown', e => {
|
183 |
switch(e.key.toLowerCase()){
|
184 |
case '1': moveCamera('top'); break;
|
|
|
190 |
case '7': moveCamera('angle2'); break;
|
191 |
case '8': moveCamera('angle3'); break;
|
192 |
case '9': moveCamera('angle4'); break;
|
193 |
+
case 'w': flyCamera('forward'); break;
|
194 |
+
case 'x': flyCamera('backward'); break;
|
195 |
+
case 'a': flyCamera('panLeft'); break;
|
196 |
+
case 'd': flyCamera('panRight'); break;
|
197 |
+
case 'q': flyCamera('rotateLeft'); break;
|
198 |
+
case 'e': flyCamera('rotateRight'); break;
|
199 |
+
case 's': flyCamera('reset'); break;
|
200 |
+
case ' ': fireRaycast(); break;
|
201 |
}
|
202 |
});
|
203 |
</script>
|
|
|
245 |
assets += "</a-assets>"
|
246 |
|
247 |
entities = ""
|
248 |
+
if vids:
|
249 |
+
# Use the first video as a large ground plane
|
250 |
+
v = vids[0]; s = Path(v).stem
|
251 |
+
entities += (f'<a-video src="#{s}" width="{gw}" height="{gh}" '
|
252 |
+
f'rotation="-90 0 0" position="0 0.05 0" '
|
253 |
+
'loop autoplay></a-video>')
|
254 |
+
else:
|
255 |
+
# Generate individual tiles if no video
|
256 |
+
sx = -gw/2; sz = -gh/2
|
257 |
+
for i in range(gw):
|
258 |
+
for j in range(gh):
|
259 |
+
x,y,z = sx+i,0,sz+j
|
260 |
+
if imgs:
|
261 |
+
img = random.choice(imgs); s = Path(img).stem
|
262 |
+
entities += (f'<a-plane src="#{s}" width="1" height="1" '
|
263 |
+
f'rotation="-90 0 0" position="{x} 0 {z}"></a-plane>')
|
264 |
+
# Always generate models
|
265 |
+
sx = -gw/2; sz = -gh/2
|
266 |
for i in range(gw):
|
267 |
for j in range(gh):
|
268 |
x,y,z = sx+i,0,sz+j
|
|
|
|
|
|
|
|
|
269 |
if models:
|
270 |
+
m = random.choice(models); ext = m.split('.')[-1]; s = Path(m).stem
|
271 |
+
entities += create_aframe_entity(s, ext, f"{x} 0 {z}")
|
|
|
|
|
|
|
|
|
|
|
272 |
return assets, entities
|
273 |
|
274 |
def main():
|
|
|
289 |
cols[1].button("↙️ Angle 3", on_click=lambda: st.session_state.update({'camera_view': 'angle3'}))
|
290 |
cols[2].button("↘️ Angle 4", on_click=lambda: st.session_state.update({'camera_view': 'angle4'}))
|
291 |
|
292 |
+
st.markdown("### ✈️ Flight Controls")
|
293 |
+
st.markdown("**Fly Camera** 🎮")
|
294 |
+
cols = st.columns(3)
|
295 |
+
cols[0].button("Q Rotate Left", on_click=lambda: st.session_state.update({'fly_action': 'rotateLeft'}))
|
296 |
+
cols[1].button("W Forward", on_click=lambda: st.session_state.update({'fly_action': 'forward'}))
|
297 |
+
cols[2].button("E Rotate Right", on_click=lambda: st.session_state.update({'fly_action': 'rotateRight'}))
|
298 |
+
cols = st.columns(3)
|
299 |
+
cols[0].button("A Pan Left", on_click=lambda: st.session_state.update({'fly_action': 'panLeft'}))
|
300 |
+
cols[1].button("S Reset", on_click=lambda: st.session_state.update({'fly_action': 'reset'}))
|
301 |
+
cols[2].button("D Pan Right", on_click=lambda: st.session_state.update({'fly_action': 'panRight'}))
|
302 |
+
cols = st.columns(1)
|
303 |
+
cols[0].button("X Backward", on_click=lambda: st.session_state.update({'fly_action': 'backward'}))
|
304 |
+
|
305 |
st.markdown("### ➕ Add Media Files")
|
306 |
ups = st.file_uploader("Add files (png, jpeg, obj, glb, mp4, etc.):", accept_multiple_files=True)
|
307 |
st.markdown("### 📋 Uploaded Model Files")
|
|
|
352 |
assets, ents = generate_tilemap(files, directory, 8, 8)
|
353 |
scene += assets + ents + "</a-scene>"
|
354 |
|
355 |
+
view_cmd = st.session_state.get('camera_view', 'top')
|
356 |
+
if view_cmd:
|
357 |
+
scene += f"<script>moveCamera('{view_cmd}');</script>"
|
358 |
st.session_state.pop('camera_view', None)
|
359 |
|
360 |
+
fly_cmd = st.session_state.get('fly_action')
|
361 |
+
if fly_cmd:
|
362 |
+
scene += f"<script>flyCamera('{fly_cmd}');</script>"
|
363 |
+
st.session_state.pop('fly_action', None)
|
364 |
+
|
365 |
loader = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-extras.loaders.min.js"></script>'
|
366 |
|
367 |
st.components.v1.html(
|