Spaces:
Running
Running
import streamlit as st | |
import os, base64, shutil, random | |
from pathlib import Path | |
def load_aframe_and_extras(): | |
return """ | |
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script> | |
<script src="https://unpkg.com/[email protected]/dist/aframe-event-set-component.min.js"></script> | |
<script> | |
let score = 0; | |
AFRAME.registerComponent('draggable', { | |
init: function () { | |
this.el.setAttribute('class', 'raycastable'); | |
this.el.setAttribute('cursor-listener', ''); | |
this.dragHandler = this.dragMove.bind(this); | |
this.el.sceneEl.addEventListener('mousemove', this.dragHandler); | |
this.el.addEventListener('mousedown', this.onDragStart.bind(this)); | |
this.el.addEventListener('mouseup', this.onDragEnd.bind(this)); | |
this.camera = document.querySelector('[camera]'); | |
}, | |
remove: function () { | |
this.el.removeAttribute('cursor-listener'); | |
this.el.sceneEl.removeEventListener('mousemove', this.dragHandler); | |
}, | |
onDragStart: function (evt) { | |
this.isDragging = true; | |
this.el.emit('dragstart'); | |
}, | |
onDragEnd: function (evt) { | |
this.isDragging = false; | |
this.el.emit('dragend'); | |
}, | |
dragMove: function (evt) { | |
if (!this.isDragging) return; | |
let mouseX = evt.clientX / window.innerWidth * 2 - 1; | |
let mouseY = -(evt.clientY / window.innerHeight * 2) + 1; | |
let position = new THREE.Vector3(mouseX, mouseY, -5); | |
position.unproject(this.camera.components.camera.camera); | |
let direction = position.sub(this.camera.object3D.position).normalize(); | |
let distance = -this.camera.object3D.position.z / direction.z; | |
let newPosition = this.camera.object3D.position.clone().add(direction.multiplyScalar(distance)); | |
this.el.setAttribute('position', {x: newPosition.x, y: newPosition.y, z: this.el.getAttribute('position').z}); | |
} | |
}); | |
AFRAME.registerComponent('cursor-listener', { | |
init: function () { | |
this.el.addEventListener('mouseenter', function (evt) { | |
this.setAttribute('material', {color: 'red'}); | |
}); | |
this.el.addEventListener('mouseleave', function (evt) { | |
this.setAttribute('material', {color: 'blue'}); | |
}); | |
this.el.addEventListener('click', function (evt) { | |
score++; | |
document.getElementById('score').setAttribute('value', 'Score: ' + score); | |
}); | |
} | |
}); | |
</script> | |
""" | |
def create_environment(scene): | |
sky = scene.entity( | |
geometry="primitive: sphere; radius: 5000", | |
material="color: #ADD8E6; shader: flat; side: back" # Light blue sky | |
) | |
ground = scene.entity( | |
geometry="primitive: plane; width: 100; height: 100", | |
material="color: #7CFC00; side: double", # Lawn green ground | |
rotation="-90 0 0" | |
) | |
return sky, ground | |
def create_drag_target(scene, x, y, z, color='blue'): | |
target = scene.entity( | |
geometry=f"primitive: box; width: 1; height: 1; depth: 1", | |
material=f"color: {color}", | |
position=f"{x} {y} {z}", | |
draggable="" | |
) | |
return target | |
def main(): | |
st.title("Interactive A-Frame Scene") | |
html_string = f""" | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>A-Frame Example</title> | |
{load_aframe_and_extras()} | |
</head> | |
<body> | |
<a-scene cursor="rayOrigin: mouse" raycaster="objects: .raycastable"> | |
<a-camera position="0 1.6 0"></a-camera> | |
<a-entity id="environment"></a-entity> | |
<a-text id="score" value="Score: 0" position="-2 2 -3" color="black"></a-text> | |
<a-entity id="drag-targets"></a-entity> | |
</a-scene> | |
</body> | |
</html> | |
""" | |
st.components.v1.html(html_string, height=600, scrolling=False) | |
with st.sidebar: | |
st.header("Scene Controls") | |
num_targets = st.slider("Number of Drag Targets", min_value=1, max_value=10, value=3) | |
scene = st.components.v1 # This won't work as expected for direct A-Frame manipulation | |
environment = scene.get("environment") # This also won't work | |
drag_targets = scene.get("drag-targets") # And this won't work | |
if environment is not None: | |
create_environment(environment) # This will likely cause errors | |
if drag_targets is not None: | |
for i in range(num_targets): | |
x = random.uniform(-5, 5) | |
y = 1 | |
z = random.uniform(-5, -2) | |
create_drag_target(drag_targets, x, y, z) # Potential error here too | |
if __name__ == "__main__": | |
main() |