UNPKG

@trap_stevo/legendarybuilderproreact-ui

Version:

The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton

336 lines 14.5 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React, { useEffect, useRef, useMemo } from "react"; import { Canvas, useThree, useFrame } from "@react-three/fiber"; import { OrthographicCamera } from "@react-three/drei"; import { EffectComposer, Bloom, Noise } from "@react-three/postprocessing"; import { useHUDTerrain } from "./HUDTerrainProvider.js"; var Entity = function Entity(_ref) { var entity = _ref.entity, zoom = _ref.zoom, zoomLimits = _ref.zoomLimits, renderEntity = _ref.renderEntity; var minZoom = (zoomLimits === null || zoomLimits === void 0 ? void 0 : zoomLimits.min) || 0.1; var maxZoom = (zoomLimits === null || zoomLimits === void 0 ? void 0 : zoomLimits.max) || 100; var zoomRatio = (zoom - minZoom) / (maxZoom - minZoom); var clampedZoomRatio = Math.max(0, Math.min(1, zoomRatio)); var minSize = Math.max(20, entity.radius * 0.2); var maxSize = entity.radius; var adjustedRadius = minSize + (maxSize - minSize) * (1 - clampedZoomRatio); return /*#__PURE__*/React.createElement("group", { key: entity.id, position: [entity.x, entity.y, 0] }, renderEntity(_objectSpread(_objectSpread({}, entity), {}, { radius: adjustedRadius, zoom: zoom, maxZoom: maxZoom, minZoom: minZoom, zoomRatio: clampedZoomRatio }))); }; var GridOverlay = function GridOverlay(_ref2) { var viewBox = _ref2.viewBox, zoom = _ref2.zoom, _ref2$gridColor = _ref2.gridColor, gridColor = _ref2$gridColor === void 0 ? "rgba(255,255,255,0.1)" : _ref2$gridColor; var lines = []; var gridSpacing = 100 / zoom; var startX = Math.floor(viewBox.xRange[0] / gridSpacing) * gridSpacing; var endX = viewBox.xRange[1]; var startY = Math.floor(viewBox.yRange[0] / gridSpacing) * gridSpacing; var endY = viewBox.yRange[1]; for (var x = startX; x <= endX; x += gridSpacing) { lines.push( /*#__PURE__*/React.createElement("lineSegments", { key: "x-".concat(x) }, /*#__PURE__*/React.createElement("bufferGeometry", null, /*#__PURE__*/React.createElement("bufferAttribute", { attach: "attributes-position", count: 2, array: new Float32Array([x, startY, 0, x, endY, 0]), itemSize: 3 })), /*#__PURE__*/React.createElement("lineBasicMaterial", { color: gridColor, linewidth: 1 }))); } for (var y = startY; y <= endY; y += gridSpacing) { lines.push( /*#__PURE__*/React.createElement("lineSegments", { key: "y-".concat(y) }, /*#__PURE__*/React.createElement("bufferGeometry", null, /*#__PURE__*/React.createElement("bufferAttribute", { attach: "attributes-position", count: 2, array: new Float32Array([startX, y, 0, endX, y, 0]), itemSize: 3 })), /*#__PURE__*/React.createElement("lineBasicMaterial", { color: gridColor, linewidth: 1 }))); } return /*#__PURE__*/React.createElement(React.Fragment, null, lines); }; var CameraControls = function CameraControls(_ref3) { var enableZoom = _ref3.enableZoom, enablePanning = _ref3.enablePanning, zoomLimits = _ref3.zoomLimits; var _useThree = useThree(), camera = _useThree.camera, gl = _useThree.gl; var state = useRef({ isDragging: false, lastX: 0, lastY: 0, lastDistance: null }); useEffect(function () { var preventDefault = function preventDefault(e) { return e.preventDefault(); }; var handleWheel = function handleWheel(e) { if (!enableZoom) return; e.preventDefault(); var delta = e.deltaY * 0.001; var newZoom = camera.zoom * (1 - delta); if (zoomLimits) { newZoom = Math.max(zoomLimits.min * 0.01, Math.min(zoomLimits.max * 0.01, newZoom)); } camera.zoom = newZoom; camera.updateProjectionMatrix(); }; var handleMouseDown = function handleMouseDown(e) { if (!enablePanning) return; state.current.isDragging = true; state.current.lastX = e.clientX; state.current.lastY = e.clientY; }; var handleMouseUp = function handleMouseUp() { state.current.isDragging = false; }; var handleMouseMove = function handleMouseMove(e) { if (!enablePanning || !state.current.isDragging) return; var dx = (e.clientX - state.current.lastX) / camera.zoom; var dy = (e.clientY - state.current.lastY) / camera.zoom; camera.position.x -= dx; camera.position.y += dy; state.current.lastX = e.clientX; state.current.lastY = e.clientY; }; var handleTouchMove = function handleTouchMove(e) { if (!enableZoom || e.touches.length !== 2) return; e.preventDefault(); var _e$touches = _slicedToArray(e.touches, 2), touch1 = _e$touches[0], touch2 = _e$touches[1]; var dx = touch1.clientX - touch2.clientX; var dy = touch1.clientY - touch2.clientY; var distance = Math.sqrt(dx * dx + dy * dy); if (state.current.lastDistance) { var delta = distance - state.current.lastDistance; var newZoom = camera.zoom * (1 + delta * 0.005); if (zoomLimits) { newZoom = Math.max(zoomLimits.min * 0.01, Math.min(zoomLimits.max * 0.01, newZoom)); } camera.zoom = newZoom; camera.updateProjectionMatrix(); } state.current.lastDistance = distance; }; var handleTouchEnd = function handleTouchEnd() { state.current.lastDistance = null; }; gl.domElement.addEventListener("wheel", handleWheel, { passive: false }); gl.domElement.addEventListener("mousedown", handleMouseDown); gl.domElement.addEventListener("mouseup", handleMouseUp); gl.domElement.addEventListener("mousemove", handleMouseMove); gl.domElement.addEventListener("touchmove", handleTouchMove, { passive: false }); gl.domElement.addEventListener("touchend", handleTouchEnd); gl.domElement.addEventListener("gesturestart", preventDefault, { passive: false }); gl.domElement.addEventListener("gesturechange", preventDefault, { passive: false }); gl.domElement.addEventListener("gestureend", preventDefault, { passive: false }); return function () { gl.domElement.removeEventListener("wheel", handleWheel); gl.domElement.removeEventListener("mousedown", handleMouseDown); gl.domElement.removeEventListener("mouseup", handleMouseUp); gl.domElement.removeEventListener("mousemove", handleMouseMove); gl.domElement.removeEventListener("touchmove", handleTouchMove); gl.domElement.removeEventListener("touchend", handleTouchEnd); gl.domElement.removeEventListener("gesturestart", preventDefault); gl.domElement.removeEventListener("gesturechange", preventDefault); gl.domElement.removeEventListener("gestureend", preventDefault); }; }, [enableZoom, enablePanning, zoomLimits, camera, gl]); return null; }; var HUDTerrainScene = function HUDTerrainScene(_ref4) { var _ref4$backgroundEffec = _ref4.backgroundEffects, backgroundEffects = _ref4$backgroundEffec === void 0 ? [] : _ref4$backgroundEffec, _ref4$sceneEffects = _ref4.sceneEffects, sceneEffects = _ref4$sceneEffects === void 0 ? [] : _ref4$sceneEffects, visibilityMargin = _ref4.visibilityMargin, startAtPoint = _ref4.startAtPoint, showGrid = _ref4.showGrid, gridColor = _ref4.gridColor, renderEntity = _ref4.renderEntity, background = _ref4.background, enableZoom = _ref4.enableZoom, enablePanning = _ref4.enablePanning, zoomLimits = _ref4.zoomLimits; var _useHUDTerrain = useHUDTerrain(), registerCamera = _useHUDTerrain.registerCamera, cameraRef = _useHUDTerrain.cameraRef, entities = _useHUDTerrain.entities, rawZoom = _useHUDTerrain.zoom, viewBox = _useHUDTerrain.viewBox, jumpToPoint = _useHUDTerrain.jumpToPoint, setZoom = _useHUDTerrain.setZoom; var clampedZoom = useMemo(function () { return Math.max(zoomLimits.min, Math.min(zoomLimits.max, rawZoom)); }, [rawZoom, zoomLimits]); useEffect(function () { if (rawZoom !== clampedZoom) { setZoom(clampedZoom); } }, [rawZoom, clampedZoom, setZoom]); useEffect(function () { if (cameraRef.current) { registerCamera(cameraRef.current); } }, []); useEffect(function () { if (startAtPoint) { var timeout = setTimeout(function () { jumpToPoint(startAtPoint.x, startAtPoint.y); }, 50); return function () { return clearTimeout(timeout); }; } }, [JSON.stringify(startAtPoint)]); var zoom = clampedZoom; var cameraZoom = zoom * 0.01; var maxGrainOpacity = 0.05; var baseOpacity = (zoomLimits.max - zoom) / (zoomLimits.max - zoomLimits.min) * maxGrainOpacity; var isEntityVisible = function isEntityVisible(entity) { var margin = visibilityMargin * zoom; if (entity.radius) { return entity.x + entity.radius > viewBox.xRange[0] - margin && entity.x - entity.radius < viewBox.xRange[1] + margin && entity.y + entity.radius > viewBox.yRange[0] - margin && entity.y - entity.radius < viewBox.yRange[1] + margin; } else if (entity.width && entity.height) { return entity.x + entity.width > viewBox.xRange[0] - margin && entity.x < viewBox.xRange[1] + margin && entity.y + entity.height > viewBox.yRange[0] - margin && entity.y < viewBox.yRange[1] + margin; } return false; }; var renderBackgroundEffects = function renderBackgroundEffects() { return backgroundEffects.map(function (effect, index) { var position = effect.position, width = effect.width, height = effect.height, element = effect.element; var isVisible = viewBox.xRange[1] > position[0] - width / 2 && viewBox.xRange[0] < position[0] + width / 2 && viewBox.yRange[1] > position[1] - height / 2 && viewBox.yRange[0] < position[1] + height / 2; if (!isVisible) return null; return /*#__PURE__*/React.cloneElement(element, { key: index }); }); }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(OrthographicCamera, { ref: cameraRef, makeDefault: true, zoom: cameraZoom, position: [0, 0, 10] }), /*#__PURE__*/React.createElement(CameraControls, { enableZoom: enableZoom, enablePanning: enablePanning, zoomLimits: zoomLimits }), /*#__PURE__*/React.createElement("ambientLight", { intensity: 0.5 }), /*#__PURE__*/React.createElement("pointLight", { position: [300, 200, 300], intensity: 1.69 }), /*#__PURE__*/React.createElement("mesh", { position: [(viewBox.xRange[0] + viewBox.xRange[1]) / 2, (viewBox.yRange[0] + viewBox.yRange[1]) / 2, -1] }, /*#__PURE__*/React.createElement("planeGeometry", { args: [viewBox.xRange[1] - viewBox.xRange[0], viewBox.yRange[1] - viewBox.yRange[0]] }), /*#__PURE__*/React.createElement("meshBasicMaterial", { color: background })), renderBackgroundEffects(), showGrid && /*#__PURE__*/React.createElement(GridOverlay, { viewBox: viewBox, zoom: zoom, gridColor: gridColor }), entities.filter(isEntityVisible).map(function (entity) { return /*#__PURE__*/React.createElement(Entity, { key: entity.id, entity: entity, zoomLimits: zoomLimits, zoom: zoom, renderEntity: renderEntity }); }), /*#__PURE__*/React.createElement(EffectComposer, null, /*#__PURE__*/React.createElement(Bloom, { luminanceThreshold: 0.2, luminanceSmoothing: 0.9, intensity: 1.2 }), /*#__PURE__*/React.createElement(Noise, { opacity: baseOpacity }), sceneEffects === null || sceneEffects === void 0 ? void 0 : sceneEffects.map(function (effect, index) { return /*#__PURE__*/React.createElement(React.Fragment, { key: "scene-effect-".concat(index) }, effect); }))); }; var HUDTerrain = function HUDTerrain(_ref5) { var _ref5$backgroundEffec = _ref5.backgroundEffects, backgroundEffects = _ref5$backgroundEffec === void 0 ? [] : _ref5$backgroundEffec, _ref5$sceneEffects = _ref5.sceneEffects, sceneEffects = _ref5$sceneEffects === void 0 ? [] : _ref5$sceneEffects, _ref5$visibilityMargi = _ref5.visibilityMargin, visibilityMargin = _ref5$visibilityMargi === void 0 ? 200 : _ref5$visibilityMargi, _ref5$enablePanning = _ref5.enablePanning, enablePanning = _ref5$enablePanning === void 0 ? true : _ref5$enablePanning, _ref5$enableZoom = _ref5.enableZoom, enableZoom = _ref5$enableZoom === void 0 ? true : _ref5$enableZoom, _ref5$background = _ref5.background, background = _ref5$background === void 0 ? "#000" : _ref5$background, renderEntity = _ref5.renderEntity, _ref5$showGrid = _ref5.showGrid, showGrid = _ref5$showGrid === void 0 ? true : _ref5$showGrid, _ref5$gridColor = _ref5.gridColor, gridColor = _ref5$gridColor === void 0 ? "rgba(255,255,255,0.1)" : _ref5$gridColor, _ref5$startAtPoint = _ref5.startAtPoint, startAtPoint = _ref5$startAtPoint === void 0 ? { x: 0, y: 0 } : _ref5$startAtPoint; var _useHUDTerrain2 = useHUDTerrain(), jumpToPoint = _useHUDTerrain2.jumpToPoint, zoomLimits = _useHUDTerrain2.zoomLimits; return /*#__PURE__*/React.createElement(Canvas, { orthographic: true, dpr: [1, 2], style: { width: "100vw", height: "100vh" } }, /*#__PURE__*/React.createElement(HUDTerrainScene, { backgroundEffects: backgroundEffects, sceneEffects: sceneEffects, visibilityMargin: visibilityMargin, startAtPoint: startAtPoint, showGrid: showGrid, gridColor: gridColor, renderEntity: renderEntity, background: background, enableZoom: enableZoom, enablePanning: enablePanning, zoomLimits: zoomLimits })); }; export default HUDTerrain;