|
59 | 59 | <section id="playground" class="h-full"> |
60 | 60 | <div class="h-full"> |
61 | 61 | <div class="bg-gray-900 flex flex-col lg:flex-row h-full"> |
62 | | - <div class="w-full lg:w-52 bg-gray-800 border-b lg:border-b-0 lg:border-r border-gray-700 p-3 flex flex-col"> |
63 | | - <div class="font-bold text-gray-300 mb-2 text-sm">🧰 Toolbox</div> |
64 | | - <div class="space-y-2 flex-1"> |
| 62 | + <div class="w-full lg:w-52 bg-gray-800 border-b lg:border-b-0 lg:border-r border-gray-700 px-2 py-1.5 lg:p-3 flex flex-col"> |
| 63 | + <div class="font-bold text-gray-300 mb-1 lg:mb-2 text-sm">🧰 Toolbox</div> |
| 64 | + <div class="grid grid-cols-3 gap-1 lg:flex lg:flex-col lg:gap-2 flex-1"> |
65 | 65 | <button onclick="addPart('chassis')" |
66 | | - class="w-full bg-teal-700 hover:bg-teal-600 p-2 rounded text-white text-xs flex items-center gap-2 transition font-medium"> |
| 66 | + class="w-full bg-teal-700 hover:bg-teal-600 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex flex-col lg:flex-row items-center justify-center lg:justify-start gap-0.5 lg:gap-2 transition font-medium"> |
67 | 67 | <i class="fas fa-cube"></i> Chassis |
68 | 68 | </button> |
69 | 69 | <button onclick="addPart('wheels')" |
70 | | - class="w-full bg-orange-600 hover:bg-orange-500 p-2 rounded text-white text-xs flex items-center gap-2 transition font-medium"> |
71 | | - <i class="fas fa-circle-notch"></i> Wheels (WASD) |
| 70 | + class="w-full bg-orange-600 hover:bg-orange-500 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex flex-col lg:flex-row items-center justify-center lg:justify-start gap-0.5 lg:gap-2 transition font-medium"> |
| 71 | + <i class="fas fa-circle-notch"></i> |
| 72 | + <span class="hidden lg:inline">Wheels (WASD)</span> |
| 73 | + <span class="lg:hidden">Wheels</span> |
72 | 74 | </button> |
73 | 75 | <button onclick="addPart('lidar')" |
74 | | - class="w-full bg-red-600 hover:bg-red-500 p-2 rounded text-white text-xs flex items-center gap-2 transition font-medium"> |
| 76 | + class="w-full bg-red-600 hover:bg-red-500 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex flex-col lg:flex-row items-center justify-center lg:justify-start gap-0.5 lg:gap-2 transition font-medium"> |
75 | 77 | <i class="fas fa-satellite-dish"></i> Lidar |
76 | 78 | </button> |
77 | 79 | <button onclick="addPart('camera')" |
78 | | - class="w-full bg-blue-600 hover:bg-blue-500 p-2 rounded text-white text-xs flex items-center gap-2 transition font-medium"> |
79 | | - <i class="fas fa-video"></i> Camera (View) |
| 80 | + class="w-full bg-blue-600 hover:bg-blue-500 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex flex-col lg:flex-row items-center justify-center lg:justify-start gap-0.5 lg:gap-2 transition font-medium"> |
| 81 | + <i class="fas fa-video"></i> |
| 82 | + <span class="hidden lg:inline">Camera (View)</span> |
| 83 | + <span class="lg:hidden">Camera</span> |
80 | 84 | </button> |
81 | 85 | <button onclick="addPart('arm')" |
82 | | - class="w-full bg-purple-600 hover:bg-purple-500 p-2 rounded text-white text-xs flex items-center gap-2 transition font-medium"> |
83 | | - <i class="fas fa-hand-paper"></i> Arm (SPACE) |
| 86 | + class="w-full bg-purple-600 hover:bg-purple-500 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex flex-col lg:flex-row items-center justify-center lg:justify-start gap-0.5 lg:gap-2 transition font-medium"> |
| 87 | + <i class="fas fa-hand-paper"></i> |
| 88 | + <span class="hidden lg:inline">Arm (SPACE)</span> |
| 89 | + <span class="lg:hidden">Arm</span> |
84 | 90 | </button> |
85 | 91 | </div> |
86 | | - <button onclick="resetAll()" |
87 | | - class="mt-3 w-full bg-gray-700 hover:bg-gray-600 p-2 rounded text-gray-300 text-xs flex items-center justify-center gap-2 transition"> |
88 | | - <i class="fas fa-redo"></i> Reset All |
89 | | - </button> |
90 | | - <a href="https://github.com/alphaonelabs/alphaonelabs-virtual-robotics-playground" |
91 | | - target="_blank" |
92 | | - rel="noopener noreferrer" |
93 | | - class="mt-2 w-full bg-indigo-700 hover:bg-indigo-600 p-2 rounded text-white text-xs flex items-center justify-center gap-2 transition font-medium"> |
94 | | - <i class="fas fa-code-branch"></i> Contribute |
95 | | - </a> |
| 92 | + <div class="grid grid-cols-2 gap-1 mt-1 lg:block lg:mt-0"> |
| 93 | + <button onclick="resetAll()" |
| 94 | + class="w-full lg:mt-3 bg-gray-700 hover:bg-gray-600 p-1.5 lg:p-2 rounded text-gray-300 text-[10px] lg:text-xs flex items-center justify-center gap-1 lg:gap-2 transition"> |
| 95 | + <i class="fas fa-redo"></i> |
| 96 | + <span class="hidden lg:inline">Reset All</span> |
| 97 | + <span class="lg:hidden">Reset</span> |
| 98 | + </button> |
| 99 | + <a href="https://github.com/alphaonelabs/alphaonelabs-virtual-robotics-playground" |
| 100 | + target="_blank" |
| 101 | + rel="noopener noreferrer" |
| 102 | + class="lg:mt-2 w-full bg-indigo-700 hover:bg-indigo-600 p-1.5 lg:p-2 rounded text-white text-[10px] lg:text-xs flex items-center justify-center gap-2 transition font-medium"> |
| 103 | + <i class="fas fa-code-branch"></i> Contribute |
| 104 | + </a> |
| 105 | + </div> |
96 | 106 | </div> |
97 | 107 | <div class="flex-1 relative bg-gray-950" id="viewport-wrapper"> |
98 | 108 | <canvas id="sim-canvas" |
|
136 | 146 | Add a <strong>Chassis</strong> to start |
137 | 147 | </div> |
138 | 148 | </div> |
| 149 | + <!-- Touch Controls - mobile only --> |
| 150 | + <div class="lg:hidden absolute bottom-4 inset-x-4 flex justify-between items-end pointer-events-none"> |
| 151 | + <!-- D-pad --> |
| 152 | + <div class="grid grid-cols-3 gap-1 pointer-events-auto select-none" style="width:112px"> |
| 153 | + <div></div> |
| 154 | + <button id="btn-up" aria-label="Move forward" class="w-9 h-9 bg-gray-800/80 active:bg-gray-500 rounded text-white flex items-center justify-center"><i class="fas fa-chevron-up text-xs"></i></button> |
| 155 | + <div></div> |
| 156 | + <button id="btn-left" aria-label="Turn left" class="w-9 h-9 bg-gray-800/80 active:bg-gray-500 rounded text-white flex items-center justify-center"><i class="fas fa-chevron-left text-xs"></i></button> |
| 157 | + <div class="w-9 h-9 bg-gray-900/50 rounded"></div> |
| 158 | + <button id="btn-right" aria-label="Turn right" class="w-9 h-9 bg-gray-800/80 active:bg-gray-500 rounded text-white flex items-center justify-center"><i class="fas fa-chevron-right text-xs"></i></button> |
| 159 | + <div></div> |
| 160 | + <button id="btn-down" aria-label="Move backward" class="w-9 h-9 bg-gray-800/80 active:bg-gray-500 rounded text-white flex items-center justify-center"><i class="fas fa-chevron-down text-xs"></i></button> |
| 161 | + <div></div> |
| 162 | + </div> |
| 163 | + <!-- Pick/Drop button --> |
| 164 | + <button id="btn-space" aria-label="Pick or drop object" class="w-14 h-14 bg-purple-700/80 active:bg-purple-500 rounded-full text-white flex items-center justify-center pointer-events-auto select-none"> |
| 165 | + <i class="fas fa-hand-paper text-lg"></i> |
| 166 | + </button> |
| 167 | + </div> |
139 | 168 | </div> |
140 | 169 | <!-- Right Sidebar: Properties --> |
141 | | - <div class="w-full lg:w-52 bg-gray-800 border-t lg:border-t-0 lg:border-l border-gray-700 p-3 flex flex-col"> |
142 | | - <div class="font-bold text-gray-300 mb-2 text-sm">⚙️ Settings</div> |
143 | | - <div class="space-y-3 flex-1"> |
| 170 | + <div class="w-full lg:w-52 bg-gray-800 border-t lg:border-t-0 lg:border-l border-gray-700 px-2 py-1.5 lg:p-3 flex flex-col"> |
| 171 | + <div class="font-bold text-gray-300 mb-1 lg:mb-2 text-sm">⚙️ Settings</div> |
| 172 | + <div class="grid grid-cols-2 gap-x-3 gap-y-1 lg:block lg:space-y-3 flex-1"> |
144 | 173 | <div> |
145 | 174 | <label class="text-gray-400 text-xs flex justify-between"> |
146 | 175 | <span>Power</span><span id="power-val" class="text-teal-400">50%</span> |
|
150 | 179 | min="10" |
151 | 180 | max="100" |
152 | 181 | value="50" |
153 | | - class="w-full accent-teal-500 mt-1" |
| 182 | + class="w-full accent-teal-500 mt-0.5 lg:mt-1" |
154 | 183 | oninput="updatePower()" /> |
155 | 184 | </div> |
156 | 185 | <div> |
|
162 | 191 | min="1" |
163 | 192 | max="15" |
164 | 193 | value="5" |
165 | | - class="w-full accent-teal-500 mt-1" |
| 194 | + class="w-full accent-teal-500 mt-0.5 lg:mt-1" |
166 | 195 | oninput="updateTurn()" /> |
167 | 196 | </div> |
168 | | - <div> |
| 197 | + <div class="col-span-2 lg:col-span-1"> |
169 | 198 | <label class="text-gray-400 text-xs">Color</label> |
170 | 199 | <input type="color" |
171 | 200 | id="color-picker" |
172 | 201 | value="#0d9488" |
173 | | - class="w-full h-6 rounded mt-1 cursor-pointer" |
| 202 | + class="w-full h-5 lg:h-6 rounded mt-0.5 lg:mt-1 cursor-pointer" |
174 | 203 | oninput="updateColor()" /> |
175 | 204 | </div> |
176 | 205 | </div> |
177 | 206 | <!-- Parts & Info --> |
178 | | - <div class="mt-3 pt-3 border-t border-gray-700"> |
179 | | - <div class="text-gray-400 text-xs mb-1">Parts:</div> |
180 | | - <div id="parts-list" class="text-gray-500 text-xs">None</div> |
181 | | - <div class="mt-2 text-gray-500 text-[10px]"> |
182 | | - Blocks: <span id="block-count">0</span> |
183 | | - </div> |
184 | | - </div> |
185 | | - <!-- LiDAR Detection Panel --> |
186 | | - <div class="mt-3 pt-3 border-t border-gray-700"> |
187 | | - <div class="text-gray-400 text-xs mb-1 flex items-center gap-1.5"> |
188 | | - <span class="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulse hidden" id="detection-indicator"></span> |
189 | | - 📡 Detection: |
| 207 | + <div class="mt-1.5 lg:mt-3 pt-1.5 lg:pt-3 border-t border-gray-700 grid grid-cols-2 lg:block gap-x-3"> |
| 208 | + <div> |
| 209 | + <div class="text-gray-400 text-xs mb-0.5 lg:mb-1">Parts:</div> |
| 210 | + <div id="parts-list" class="text-gray-500 text-xs">None</div> |
| 211 | + <div class="mt-1 text-gray-500 text-[10px]"> |
| 212 | + Blocks: <span id="block-count">0</span> |
| 213 | + </div> |
190 | 214 | </div> |
191 | | - <div id="detection-info" class="text-[10px] space-y-0.5"> |
192 | | - <div class="text-gray-500">LiDAR not installed</div> |
| 215 | + <!-- LiDAR Detection Panel --> |
| 216 | + <div class="lg:mt-3 lg:pt-3 lg:border-t lg:border-gray-700"> |
| 217 | + <div class="text-gray-400 text-xs mb-0.5 lg:mb-1 flex items-center gap-1.5"> |
| 218 | + <span class="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulse hidden" id="detection-indicator"></span> |
| 219 | + 📡 Detection: |
| 220 | + </div> |
| 221 | + <div id="detection-info" class="text-[10px] space-y-0.5"> |
| 222 | + <div class="text-gray-500">LiDAR not installed</div> |
| 223 | + </div> |
193 | 224 | </div> |
194 | 225 | </div> |
195 | 226 | </div> |
|
1057 | 1088 | // Corrupted state, ignore |
1058 | 1089 | } |
1059 | 1090 | } |
| 1091 | + |
| 1092 | + // ========== TOUCH CONTROLS ========== |
| 1093 | + (function setupTouchControls() { |
| 1094 | + const btnKeyMap = { 'btn-up': 'w', 'btn-down': 's', 'btn-left': 'a', 'btn-right': 'd' }; |
| 1095 | + Object.entries(btnKeyMap).forEach(([id, key]) => { |
| 1096 | + const btn = document.getElementById(id); |
| 1097 | + if (!btn) return; |
| 1098 | + const handlePress = (e) => { e.preventDefault(); keys[key] = true; }; |
| 1099 | + const handleRelease = (e) => { e.preventDefault(); keys[key] = false; }; |
| 1100 | + btn.addEventListener('touchstart', handlePress, { passive: false }); |
| 1101 | + btn.addEventListener('touchend', handleRelease, { passive: false }); |
| 1102 | + btn.addEventListener('touchcancel', handleRelease, { passive: false }); |
| 1103 | + btn.addEventListener('mousedown', handlePress); |
| 1104 | + btn.addEventListener('mouseup', handleRelease); |
| 1105 | + btn.addEventListener('mouseleave', handleRelease); |
| 1106 | + }); |
| 1107 | + |
| 1108 | + const spaceBtn = document.getElementById('btn-space'); |
| 1109 | + if (spaceBtn) { |
| 1110 | + const triggerPick = (e) => { |
| 1111 | + e.preventDefault(); |
| 1112 | + if (!spaceJustPressed) { |
| 1113 | + spaceJustPressed = true; |
| 1114 | + handlePickDrop(); |
| 1115 | + setTimeout(() => { spaceJustPressed = false; }, 300); |
| 1116 | + } |
| 1117 | + }; |
| 1118 | + spaceBtn.addEventListener('touchstart', triggerPick, { passive: false }); |
| 1119 | + spaceBtn.addEventListener('mousedown', triggerPick); |
| 1120 | + } |
| 1121 | + })(); |
1060 | 1122 | </script> |
1061 | 1123 | </body> |
1062 | 1124 | </html> |
0 commit comments