diff --git a/src/usn-frontend/src/app/components/Player/Player.tsx b/src/usn-frontend/src/app/components/Player/Player.tsx index 9bc84b6..d663cbd 100644 --- a/src/usn-frontend/src/app/components/Player/Player.tsx +++ b/src/usn-frontend/src/app/components/Player/Player.tsx @@ -1,4 +1,12 @@ -import React, { useState, useEffect } from 'react'; +"use client"; +import { Canvas } from '@react-three/fiber'; +import { OrbitControls, useGLTF, Line, Text } from '@react-three/drei'; +import React, { useState, useEffect, useRef } from 'react'; +import { Drone, BaseStation } from '../Threejs/Models'; +import { PlayCircleIcon } from '@heroicons/react/24/outline'; +import FormComponent from '../ObjectProps/FormComponent'; +import Modal from '../Modal/Modal'; + interface Player { Click: () => void; // клик по кнопке @@ -59,7 +67,8 @@ const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate } }; return ( -
+
+
= ({ Click, TimeStep, TimeEnd, onTimeUpdate } ); }; + +interface IPlayerTsInstance { +} + +const PlayerTsInstance : React.FC = () => { + const [drones, setDrones] = useState([]); + const [baseStations, setBaseStations] = useState([]); + const [selectedObject, setSelectedObject] = useState<{ type: 'drone' | 'baseStation'; id: number } | null>(null); + const orbitControlsRef = useRef(null); // Reference to OrbitControls + + const addDrone = (drone?: Drone) => { + setDrones((prev) => [ + ...prev, + drone || { + id: prev.length, + name: `Drone ${prev.length + 1}`, + position: [Math.random() * 10, 5, Math.random() * 10], + frequency: Math.random() * 100 + 400, // Example frequency range between 400-500 + signalRadius: Math.random() * 5 + 5, // Example signal radius between 5-10 + }, + ]); + }; + + const addBaseStation = (baseStation?: BaseStation) => { + setBaseStations((prev) => [ + ...prev, + baseStation || { + id: prev.length, + name: `Base Station ${prev.length + 1}`, + position: [Math.random() * 10, -1, Math.random() * 10], + frequency: Math.random() * 100 + 400, // Example frequency range between 400-500 + signalRadius: Math.random() * 5 + 5, // Example signal radius between 5-10 + antennaDirection: [0, 1, 0], + }, + ]); + }; + + + + const handleObjectClick = (type: 'drone' | 'baseStation', id: number) => { + setSelectedObject({ type, id }); + focusOnObject(type, id); + }; + + const focusOnObject = (type: 'drone' | 'baseStation', id: number) => { + const object = type === 'drone' ? drones.find((d) => d.id === id) : baseStations.find((b) => b.id === id); + if (object && orbitControlsRef.current) { + orbitControlsRef.current.target.set(...object.position); + } + }; + + const selectNextObject = (direction: 'next' | 'prev') => { + if (!selectedObject) return; + + const currentList = selectedObject.type === 'drone' ? drones : baseStations; + const currentIndex = currentList.findIndex((obj) => obj.id === selectedObject.id); + const newIndex = direction === 'next' + ? (currentIndex + 1) % currentList.length + : (currentIndex - 1 + currentList.length) % currentList.length; + setSelectedObject({ type: selectedObject.type, id: currentList[newIndex].id }); + focusOnObject(selectedObject.type, currentList[newIndex].id); + }; + + return ( +
+
+
+ + + + + + + + {baseStations.map((baseStation) => ( + handleObjectClick('baseStation', baseStation.id)} + isSelected={selectedObject?.type === 'baseStation' && selectedObject.id === baseStation.id} + position={baseStation.position} + /> + ))} + {drones.map((drone) => ( + handleObjectClick('drone', drone.id)} + isSelected={selectedObject?.type === 'drone' && selectedObject.id === drone.id} + /> + ))} + {drones.flatMap((drone) => ( + baseStations.map((baseStation) => { + const distance = Math.sqrt( + Math.pow(drone.position[0] - baseStation.position[0], 2) + + Math.pow(drone.position[1] - baseStation.position[1], 2) + + Math.pow(drone.position[2] - baseStation.position[2], 2) + ); + + if (distance <= drone.signalRadius && distance <= baseStation.signalRadius) { + return ( + + ); + } + return null; + }) + ))} + {baseStations.map((baseStation) => ( + baseStation.signalRadius > 0 && ( + + + + + ) + ))} + {drones.map((drone) => ( + drone.signalRadius > 0 && ( + + + + + ) + ))} + +
+ +
+ + +
+ + +
+ ); +}; + + +// Модель карты +const MapModel = () => { + const { scene } = useGLTF('/map/map.glb'); + return ; +}; +// Модель дрона +const DroneModel = ({ position, droneName, onClick, isSelected }: { position: [number, number, number]; droneName?: string; onClick: () => void; isSelected: boolean }) => { + const { scene } = useGLTF('/objects/drone.glb'); + return ( + + + {/* Добавляем текстовую подпись над дроном */} + + {droneName} + + {isSelected && ( + + + + + )} + + ); +}; +// Модель базовой станции +const BaseStationModel = ({ position, onClick, isSelected }: { position: [number, number, number]; onClick: () => void; isSelected: boolean }) => { + const { scene } = useGLTF('/objects/bs.glb'); + return ( + + + {isSelected && ( + + + + + )} + + ); +}; + + export default InitPlayer;