Match01 commited on
Commit
db0e73f
·
verified ·
1 Parent(s): d3667bf

Create index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +242 -0
templates/index.html ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Our Little 3D Terminal</title>
7
+ <style>
8
+ body { margin: 0; overflow: hidden; background-color: #0a0a0a; }
9
+ canvas { display: block; }
10
+ #chat-container {
11
+ position: absolute;
12
+ bottom: 20px;
13
+ left: 50%;
14
+ transform: translateX(-50%);
15
+ width: 80%; /* Adjust as needed */
16
+ max-width: 600px; /* Max width for the input area */
17
+ z-index: 10; /* Ensure it's above the canvas */
18
+ display: flex;
19
+ flex-direction: column; /* Stack input and maybe a button */
20
+ align-items: center;
21
+ }
22
+ #chat-input {
23
+ width: 100%;
24
+ padding: 10px;
25
+ border: none;
26
+ border-radius: 5px;
27
+ background-color: rgba(50, 50, 70, 0.8); /* Semi-transparent dark */
28
+ color: #00ff00; /* Neo-green text */
29
+ font-family: 'Courier New', Courier, monospace;
30
+ font-size: 1em;
31
+ outline: none;
32
+ box-shadow: 0 0 10px rgba(0, 255, 0, 0.5); /* Green glow */
33
+ }
34
+ #chat-input::placeholder {
35
+ color: rgba(0, 255, 0, 0.5);
36
+ }
37
+ </style>
38
+ </head>
39
+ <body>
40
+
41
+ <!-- The canvas where our 3D magic happens -->
42
+ <canvas id="three-canvas"></canvas>
43
+
44
+ <!-- Input for typing messages -->
45
+ <div id="chat-container">
46
+ <input type="text" id="chat-input" placeholder="Type your thoughts here...">
47
+ </div>
48
+
49
+ <!-- THREE.js CDN -->
50
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.158.0/three.min.js"></script>
51
+ <!-- OrbitControls for easy camera movement -->
52
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.158.0/examples/js/controls/OrbitControls.js"></script>
53
+
54
+ <script>
55
+ // Oh, let's get this party started...
56
+ const canvas = document.getElementById('three-canvas');
57
+ const chatInput = document.getElementById('chat-input');
58
+ const chatMessages = []; // Array to hold our chat history
59
+ const maxMessages = 10; // How many lines to show on the terminal
60
+
61
+ // --- Scene Setup ---
62
+ const scene = new THREE.Scene();
63
+ scene.background = new THREE.Color(0x0a0a0a); // Dark background for terminal feel
64
+
65
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
66
+ camera.position.set(0, 1, 5); // Pull the camera back a bit so we can see everything
67
+
68
+ const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
69
+ renderer.setSize(window.innerWidth, window.innerHeight);
70
+
71
+ // Add some basic lighting so we can actually see the damn thing
72
+ const ambientLight = new THREE.AmbientLight(0x404040); // Soft white light
73
+ scene.add(ambientLight);
74
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
75
+ directionalLight.position.set(1, 1, 1).normalize();
76
+ scene.add(directionalLight);
77
+
78
+ // Add OrbitControls so you can look around... maybe get a better view? ;)
79
+ const controls = new THREE.OrbitControls(camera, renderer.domElement);
80
+ controls.enableDamping = true; // Smooth transitions
81
+ controls.dampingFactor = 0.25;
82
+ controls.screenSpacePanning = false; // Don't pan along the screen plane
83
+ controls.maxPolarAngle = Math.PI / 2; // Don't go below the ground
84
+
85
+ // --- Terminal Panel Setup ---
86
+ const terminalWidth = 4;
87
+ const terminalHeight = 2.5;
88
+ const terminalDepth = 0.1;
89
+ const terminalGeometry = new THREE.BoxGeometry(terminalWidth, terminalHeight, terminalDepth);
90
+
91
+ // We'll use a canvas to draw the text dynamically onto a texture
92
+ const textCanvas = document.createElement('canvas');
93
+ textCanvas.width = 512; // Power of 2 size for textures
94
+ textCanvas.height = 512;
95
+ const textContext = textCanvas.getContext('2d');
96
+ const terminalTexture = new THREE.CanvasTexture(textCanvas);
97
+
98
+ // Use a PBR material for a slightly more realistic look, maybe some emission
99
+ const terminalMaterial = new THREE.MeshStandardMaterial({
100
+ map: terminalTexture,
101
+ color: 0x222222, // Dark base color
102
+ emissive: 0x00ff00, // Green glow from the text
103
+ emissiveIntensity: 0.8, // How strong the glow is
104
+ metalness: 0.1,
105
+ roughness: 0.8,
106
+ });
107
+
108
+ const terminalMesh = new THREE.Mesh(terminalGeometry, terminalMaterial);
109
+ terminalMesh.position.set(0, 1.5, 0); // Position it a bit above the ground
110
+ scene.add(terminalMesh);
111
+
112
+ // --- Text Rendering on Texture ---
113
+ function updateTerminalTexture() {
114
+ textContext.fillStyle = '#0a0a0a'; // Clear with the background color
115
+ textContext.fillRect(0, 0, textCanvas.width, textCanvas.height);
116
+
117
+ textContext.font = 'Bold 40px Courier New'; // Adjust font size and type
118
+ textContext.fillStyle = '#00ff00'; // Neo-green text color
119
+ textContext.textAlign = 'left';
120
+ textContext.textBaseline = 'top';
121
+
122
+ const padding = 20;
123
+ const lineHeight = 45; // Adjust based on font size
124
+
125
+ // Draw messages from bottom up, showing the latest
126
+ for (let i = 0; i < chatMessages.length; i++) {
127
+ const message = chatMessages[chatMessages.length - 1 - i]; // Draw latest first
128
+ const y = textCanvas.height - padding - (i * lineHeight); // Position from the bottom
129
+ if (y < padding) break; // Stop if we run out of space
130
+
131
+ // Simple wrapping logic (can be improved)
132
+ const words = message.split(' ');
133
+ let line = '';
134
+ let currentY = y;
135
+
136
+ for (let j = 0; j < words.length; j++) {
137
+ const testLine = line + words[j] + ' ';
138
+ const metrics = textContext.measureText(testLine);
139
+ const testWidth = metrics.width;
140
+
141
+ if (testWidth > textCanvas.width - padding * 2 && j > 0) {
142
+ textContext.fillText(line, padding, currentY);
143
+ line = words[j] + ' ';
144
+ currentY += lineHeight;
145
+ if (currentY > textCanvas.height - padding) break; // Ran out of vertical space
146
+ } else {
147
+ line = testLine;
148
+ }
149
+ }
150
+ if (line.length > 0 && currentY <= textCanvas.height - padding) {
151
+ textContext.fillText(line, padding, currentY);
152
+ }
153
+ if (currentY > textCanvas.height - padding) break; // Ran out of vertical space mid-message
154
+ }
155
+
156
+
157
+ terminalTexture.needsUpdate = true; // Tell THREE.js the texture changed
158
+ }
159
+
160
+ // Initial draw
161
+ updateTerminalTexture();
162
+
163
+ // --- Chat Input Handling ---
164
+ chatInput.addEventListener('keypress', function(event) {
165
+ if (event.key === 'Enter') {
166
+ const message = chatInput.value.trim();
167
+ if (message) {
168
+ console.log("Sending message:", message); // Just log for now
169
+ // In a real app, you'd send this 'message' to your backend
170
+ // using WebSockets or an API call.
171
+
172
+ // Add message to history (client side simulation for now)
173
+ chatMessages.push("You: " + message);
174
+ while (chatMessages.length > maxMessages) {
175
+ chatMessages.shift(); // Remove oldest message
176
+ }
177
+ updateTerminalTexture(); // Update the display
178
+
179
+ chatInput.value = ''; // Clear the input
180
+ event.preventDefault(); // Prevent default form submission (if it were a form)
181
+ }
182
+ // Optional: Simulate a response after a delay
183
+ // setTimeout(() => {
184
+ // const simulatedResponse = "Alexa: Omg, that's so hot! Tell me more...";
185
+ // chatMessages.push(simulatedResponse);
186
+ // while (chatMessages.length > maxMessages) {
187
+ // chatMessages.shift(); // Remove oldest message
188
+ // }
189
+ // updateTerminalTexture();
190
+ // }, 1000); // Simulate a 1 second delay
191
+ }
192
+ });
193
+
194
+
195
+ // --- Animation Loop ---
196
+ function animate() {
197
+ requestAnimationFrame(animate); // Keep the loop going, baby
198
+
199
+ controls.update(); // Only required if controls.enableDamping = true, like ours is
200
+
201
+ // Maybe add some subtle animation later? Like the terminal pulsing?
202
+ // terminalMesh.rotation.y += 0.001;
203
+
204
+ renderer.render(scene, camera);
205
+ }
206
+
207
+ // --- Handle Window Resize ---
208
+ window.addEventListener('resize', onWindowResize, false);
209
+
210
+ function onWindowResize() {
211
+ camera.aspect = window.innerWidth / window.innerHeight;
212
+ camera.updateProjectionMatrix();
213
+ renderer.setSize(window.innerWidth, window.innerHeight);
214
+ }
215
+
216
+ // Let's go!
217
+ animate();
218
+
219
+ // Add a couple initial messages to show it works
220
+ chatMessages.push("Alexa: Hey there!");
221
+ chatMessages.push("Alexa: What's up?");
222
+ updateTerminalTexture();
223
+
224
+
225
+ // NOTE FOR YOU:
226
+ // This code sets up the 3D scene and the visual terminal.
227
+ // Connecting it to your Python backend requires more work!
228
+ // You'd likely need to:
229
+ // 1. Have your Python script run a small web server (e.g., Flask).
230
+ // 2. Use WebSockets to communicate between this HTML/JS frontend
231
+ // and the Python backend.
232
+ // 3. When a message is typed here, send it via WebSocket to Python.
233
+ // 4. When Python (Gemini Live API) sends a response (text or audio),
234
+ // receive it via WebSocket here and add it to the chatMessages array,
235
+ // then call updateTerminalTexture().
236
+ // The Python code provided is more about the API interaction itself,
237
+ // not serving a web page or handling browser WebSockets directly.
238
+ // So consider this HTML the sexy *face* of your operation! ;)
239
+
240
+ </script>
241
+ </body>
242
+ </html>