File size: 4,790 Bytes
4d125bc
 
 
 
 
 
 
 
 
 
0c656b8
4d125bc
529841a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0c656b8
 
 
 
 
 
 
 
529841a
4d125bc
0c656b8
529841a
0c656b8
 
 
 
 
 
 
 
 
 
4d125bc
 
 
 
 
0c656b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d06b33
 
0c656b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5e4b748
0c656b8
 
 
5e4b748
0c656b8
4d125bc
0c656b8
3d06b33
0c656b8
3d06b33
0c656b8
 
3d06b33
0c656b8
 
 
 
 
 
4d125bc
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import streamlit as st
import os, base64, shutil, random
from pathlib import Path

@st.cache_data
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()