@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
JavaScript
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;