feat: implement ofxpimapper-full-stack
- Unified setup script with OpenFrameworks and ofxPiMapper installation. - Integrated C++ source modification for 'Highlight Surface' OSC listener. - Full-featured 5-tab React/Tailwind web UI (Dashboard, Mapping, Media, Network, System). - WebSocket-based real-time vertex/surface manipulation and throttled log streaming. - Media Vault with ffprobe validation (H.264) and Mapping Manifest persistence. - Hybrid Networking UI with WiFi scanning, connection, and AP configuration. - System control endpoints for Reboot, Shutdown, and Mapping Save.
This commit is contained in:
@ -1,31 +1,40 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
const VirtualCanvas = ({ surfaces, onVertexMove, onSurfaceSelect }) => {
|
||||
const VirtualCanvas = ({ surfaces, onVertexMove, onSurfaceSelect, onSurfaceMoveStart }) => {
|
||||
return (
|
||||
<div className="relative w-full aspect-video bg-gray-900 border-2 border-gray-700 rounded-lg overflow-hidden cursor-crosshair">
|
||||
<div className="relative w-full h-full bg-gray-950 border-2 border-gray-800 rounded-lg overflow-hidden">
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
preserveAspectRatio="none"
|
||||
className="w-full h-full"
|
||||
>
|
||||
{surfaces.map((surface, sIndex) => (
|
||||
<g key={sIndex} onClick={() => onSurfaceSelect(sIndex)}>
|
||||
<g key={sIndex} onClick={(e) => { e.stopPropagation(); onSurfaceSelect(sIndex); }}>
|
||||
<polygon
|
||||
points={surface.vertices.map(v => `${v.x * 100},${v.y * 100}`).join(' ')}
|
||||
className={`${
|
||||
surface.selected ? 'fill-blue-500/50 stroke-blue-400' : 'fill-white/20 stroke-white/50'
|
||||
} stroke-1 transition-colors duration-200`}
|
||||
surface.selected ? 'fill-blue-500/40 stroke-blue-400' : 'fill-white/10 stroke-white/30'
|
||||
} stroke-1 cursor-grab active:cursor-grabbing transition-colors duration-200`}
|
||||
onMouseDown={(e) => surface.selected && onSurfaceMoveStart(e, sIndex)}
|
||||
/>
|
||||
{surface.selected && surface.vertices.map((v, vIndex) => (
|
||||
<circle
|
||||
key={vIndex}
|
||||
cx={v.x * 100}
|
||||
cy={v.y * 100}
|
||||
r="1.5"
|
||||
className="fill-blue-400 stroke-white stroke-[0.2] hover:fill-blue-200 cursor-move"
|
||||
r="1.2"
|
||||
className="fill-blue-400 stroke-white stroke-[0.2] hover:fill-white cursor-move"
|
||||
onMouseDown={(e) => onVertexMove(e, sIndex, vIndex)}
|
||||
/>
|
||||
))}
|
||||
{/* Label */}
|
||||
<text
|
||||
x={surface.vertices[0].x * 100}
|
||||
y={surface.vertices[0].y * 100 - 2}
|
||||
className="fill-white font-bold text-[3px] select-none pointer-events-none"
|
||||
>
|
||||
{surface.name || `Surface ${sIndex}`}
|
||||
</text>
|
||||
</g>
|
||||
))}
|
||||
</svg>
|
||||
|
||||
Reference in New Issue
Block a user