@trap_stevo/legendarybuilderproreact-ui
Version:
The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton
372 lines • 14.4 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
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, { createContext, useContext, useState, useEffect, useRef, useCallback } from "react";
var HUDTerrainContext = /*#__PURE__*/createContext(null);
export var HUDTerrainProvider = function HUDTerrainProvider(_ref) {
var children = _ref.children,
_ref$chunkSize = _ref.chunkSize,
chunkSize = _ref$chunkSize === void 0 ? 200 : _ref$chunkSize,
_ref$initialWorldSize = _ref.initialWorldSize,
initialWorldSize = _ref$initialWorldSize === void 0 ? 50000 : _ref$initialWorldSize,
_ref$initialZoom = _ref.initialZoom,
initialZoom = _ref$initialZoom === void 0 ? 1 : _ref$initialZoom,
_ref$initialZoomLimit = _ref.initialZoomLimits,
initialZoomLimits = _ref$initialZoomLimit === void 0 ? {
min: 1,
max: 100
} : _ref$initialZoomLimit,
_ref$startAtPoint = _ref.startAtPoint,
startAtPoint = _ref$startAtPoint === void 0 ? {
x: 0,
y: 0
} : _ref$startAtPoint;
var _useState = useState([]),
_useState2 = _slicedToArray(_useState, 2),
entities = _useState2[0],
setEntities = _useState2[1];
var _useState3 = useState([]),
_useState4 = _slicedToArray(_useState3, 2),
visibleChunks = _useState4[0],
setVisibleChunks = _useState4[1];
var _useState5 = useState(startAtPoint),
_useState6 = _slicedToArray(_useState5, 2),
cameraPosition = _useState6[0],
setCameraPosition = _useState6[1];
var _useState7 = useState(initialZoomLimits),
_useState8 = _slicedToArray(_useState7, 2),
zoomLimits = _useState8[0],
setZoomLimits = _useState8[1];
var _useState9 = useState(initialWorldSize),
_useState10 = _slicedToArray(_useState9, 2),
worldSize = _useState10[0],
setWorldSize = _useState10[1];
var _useState11 = useState(initialZoom),
_useState12 = _slicedToArray(_useState11, 2),
zoom = _useState12[0],
setZoom = _useState12[1];
var _useState13 = useState(function () {
var scaleFactor = initialZoom / initialZoomLimits.min;
var halfViewSize = worldSize / 2 * scaleFactor;
return {
xRange: [startAtPoint.x - halfViewSize, startAtPoint.x + halfViewSize],
yRange: [startAtPoint.y - halfViewSize, startAtPoint.y + halfViewSize]
};
}),
_useState14 = _slicedToArray(_useState13, 2),
viewBox = _useState14[0],
setViewBox = _useState14[1];
var followingEntityRef = useRef(null);
var trackingRefs = useRef(new Map());
var cameraRef = useRef(null);
var canvasRef = useRef(null);
var registerCamera = function registerCamera(cam) {
cameraRef.current = cam;
};
var updateVisibleChunks = function updateVisibleChunks() {
var xRange = viewBox.xRange,
yRange = viewBox.yRange;
var chunks = [];
for (var x = Math.floor(xRange[0] / chunkSize) * chunkSize; x <= xRange[1]; x += chunkSize) {
for (var y = Math.floor(yRange[0] / chunkSize) * chunkSize; y <= yRange[1]; y += chunkSize) {
chunks.push({
x: x,
y: y
});
}
}
setVisibleChunks(chunks);
};
var addEntity = function addEntity(entity) {
setEntities(function (prev) {
if (prev.some(function (e) {
return e.id === entity.id;
})) return prev;
return [].concat(_toConsumableArray(prev), [entity]);
});
};
var removeEntity = function removeEntity(entityID) {
setEntities(function (prev) {
return prev.filter(function (e) {
return e.id !== entityID;
});
});
trackingRefs.current["delete"](entityID);
};
var updateEntityPosition = function updateEntityPosition(entityID, operatorX, operatorY) {
setEntities(function (prev) {
return prev.map(function (e) {
if (e.id === entityID) {
var updatedEntity = _objectSpread(_objectSpread({}, e), {}, {
x: e.x + operatorX,
y: e.y + operatorY
});
var callback = trackingRefs.current.get(entityID);
if (callback) {
callback(entityID, updatedEntity);
}
return updatedEntity;
}
return e;
});
});
};
var updateEntityHealth = function updateEntityHealth(entityID, healthChange) {
var allowOverMax = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
setEntities(function (prev) {
return prev.map(function (e) {
if (e.id === entityID) {
var newHealth = allowOverMax ? e.health + healthChange : Math.max(0, Math.min(e.health + healthChange, e.maxHealth));
var updatedEntity = _objectSpread(_objectSpread({}, e), {}, {
health: newHealth
});
var callback = trackingRefs.current.get(entityID);
if (callback) {
callback(entityID, updatedEntity);
}
return updatedEntity;
}
return e;
});
});
};
var updateEntitySize = function updateEntitySize(entityID) {
var sizeChanges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var allowNegative = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var sizeProperties = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
var validSizeProperties = new Set(["radius", "height", "width"].concat(_toConsumableArray(Array.isArray(sizeProperties) ? sizeProperties : [])));
setEntities(function (prev) {
return prev.map(function (e) {
if (e.id === entityID) {
var updatedSizes = Object.keys(sizeChanges).reduce(function (acc, key) {
if (validSizeProperties.has(key)) {
var newSize = allowNegative ? e[key] + sizeChanges[key] : Math.max(0, e[key] + sizeChanges[key]);
return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, newSize));
}
return acc;
}, {});
if (Object.keys(updatedSizes).length === 0) {
return e;
}
var updatedEntity = _objectSpread(_objectSpread({}, e), updatedSizes);
var callback = trackingRefs.current.get(entityID);
if (callback) {
callback(entityID, updatedEntity);
}
return updatedEntity;
}
return e;
});
});
};
var updateEntity = function updateEntity(entityID, newData) {
setEntities(function (prev) {
return prev.map(function (e) {
if (e.id === entityID) {
var updatedEntity = _objectSpread(_objectSpread({}, e), newData);
var callback = trackingRefs.current.get(entityID);
if (callback) {
callback(entityID, updatedEntity);
}
return updatedEntity;
}
return e;
});
});
};
var worldToScreen = function worldToScreen(wx, wy) {
var canvas = canvasRef.current;
if (!canvas) {
return {
x: (wx - viewBox.xRange[0]) / (viewBox.xRange[1] - viewBox.xRange[0]),
y: 1 - (wy - viewBox.yRange[0]) / (viewBox.yRange[1] - viewBox.yRange[0])
};
}
return {
x: (wx - viewBox.xRange[0]) / (viewBox.xRange[1] - viewBox.xRange[0]) * canvas.width,
y: (1 - (wy - viewBox.yRange[0]) / (viewBox.yRange[1] - viewBox.yRange[0])) * canvas.height
};
};
var screenToWorld = function screenToWorld(sx, sy) {
var canvas = canvasRef.current;
return {
x: sx / canvas.width * (viewBox.xRange[1] - viewBox.xRange[0]) + viewBox.xRange[0],
y: (1 - sy / canvas.height) * (viewBox.yRange[1] - viewBox.yRange[0]) + viewBox.yRange[0]
};
};
var updateZoomedViewBox = useCallback(function () {
var inputZoom = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : zoom;
var scaleFactor = (inputZoom || zoom) / zoomLimits.min;
var halfViewSize = worldSize / 2 * scaleFactor;
return {
xRange: [startAtPoint.x - halfViewSize, startAtPoint.x + halfViewSize],
yRange: [startAtPoint.y - halfViewSize, startAtPoint.y + halfViewSize]
};
}, [worldSize, zoom, zoomLimits]);
var updateViewBox = function updateViewBox(newXRange, newYRange) {
setViewBox({
xRange: newXRange,
yRange: newYRange
});
};
var jumpToPoint = function jumpToPoint(x, y) {
if (!cameraRef.current) return;
var scaledX = x * 2;
var scaledY = y * 2;
cameraRef.current.position.set(scaledX, scaledY, 10);
cameraRef.current.updateMatrixWorld();
setCameraPosition({
x: scaledX,
y: scaledY
});
var scaleFactor = zoom / zoomLimits.min;
var halfViewSize = worldSize / 2 * scaleFactor;
setViewBox({
xRange: [x - halfViewSize, x + halfViewSize],
yRange: [y - halfViewSize, y + halfViewSize]
});
};
var placeAdjacentEntity = function placeAdjacentEntity(baseEntity, newEntity, direction) {
var baseX = baseEntity.x,
baseY = baseEntity.y,
_baseEntity$height = baseEntity.height,
baseHeight = _baseEntity$height === void 0 ? 0 : _baseEntity$height,
_baseEntity$width = baseEntity.width,
baseWidth = _baseEntity$width === void 0 ? 0 : _baseEntity$width,
_baseEntity$radius = baseEntity.radius,
baseRadius = _baseEntity$radius === void 0 ? 0 : _baseEntity$radius;
var _newEntity$width = newEntity.width,
newWidth = _newEntity$width === void 0 ? 0 : _newEntity$width,
_newEntity$height = newEntity.height,
newHeight = _newEntity$height === void 0 ? 0 : _newEntity$height,
_newEntity$radius = newEntity.radius,
newRadius = _newEntity$radius === void 0 ? 0 : _newEntity$radius;
var baseSize = baseRadius ? {
width: baseRadius * 2,
height: baseRadius * 2
} : {
width: baseWidth,
height: baseHeight
};
var newSize = newRadius ? {
width: newRadius * 2,
height: newRadius * 2
} : {
width: newWidth,
height: newHeight
};
var screenPos = worldToScreen(baseX, baseY);
var screenX = screenPos.x,
screenY = screenPos.y;
var baseOffset = baseRadius ? baseRadius : Math.max(baseSize.width, baseSize.height) / 2;
var newOffset = newRadius ? newRadius : Math.max(newSize.width, newSize.height) / 2;
switch (direction) {
case "top":
screenY -= baseOffset + newOffset;
break;
case "bottom":
screenY += baseOffset + newOffset;
break;
case "left":
screenX -= baseOffset + newOffset;
break;
case "right":
screenX += baseOffset + newOffset;
break;
case "upper-right":
screenX += baseOffset + newOffset;
screenY -= baseOffset + newOffset;
break;
case "upper-left":
screenX -= baseOffset + newOffset;
screenY -= baseOffset + newOffset;
break;
case "lower-right":
screenX += baseOffset + newOffset;
screenY += baseOffset + newOffset;
break;
case "lower-left":
screenX -= baseOffset + newOffset;
screenY += baseOffset + newOffset;
break;
default:
console.warn("Invalid direction specified");
return null;
}
var worldPos = screenToWorld(screenX, screenY);
return _objectSpread(_objectSpread({}, newEntity), {}, {
x: worldPos.x,
y: worldPos.y
});
};
var followEntity = function followEntity(entityID) {
followingEntityRef.current = entityID;
};
var stopFollowingEntity = function stopFollowingEntity() {
followingEntityRef.current = null;
};
var trackEntity = function trackEntity(entityID, callback) {
trackingRefs.current.set(entityID, callback);
};
useEffect(function () {
setZoomLimits(initialZoomLimits);
}, [JSON.stringify(initialZoomLimits)]);
useEffect(function () {
setZoom(initialZoom);
}, [initialZoom]);
useEffect(function () {
var zoomedViewBox = updateZoomedViewBox(zoom);
setViewBox(zoomedViewBox);
}, [zoom]);
useEffect(function () {
updateVisibleChunks();
}, [viewBox]);
useEffect(function () {
if (!followingEntityRef.current) {
return;
}
var entity = entities.find(function (e) {
return e.id === followingEntityRef.current;
});
if (entity) {
jumpToPoint(entity.x, entity.y);
}
}, [entities, zoom, zoomLimits]);
return /*#__PURE__*/React.createElement(HUDTerrainContext.Provider, {
value: _defineProperty(_defineProperty(_defineProperty({
registerCamera: registerCamera,
cameraPosition: cameraPosition,
cameraRef: cameraRef,
canvasRef: canvasRef,
entities: entities,
setZoomLimits: setZoomLimits,
zoomLimits: zoomLimits,
setZoom: setZoom,
zoom: zoom,
visibleChunks: visibleChunks,
followEntity: followEntity,
updateEntityPosition: updateEntityPosition,
updateEntityHealth: updateEntityHealth,
updateEntitySize: updateEntitySize,
updateEntity: updateEntity,
removeEntity: removeEntity,
addEntity: addEntity,
worldToScreen: worldToScreen,
screenToWorld: screenToWorld,
updateZoomedViewBox: updateZoomedViewBox,
updateViewBox: updateViewBox,
viewBox: viewBox,
placeAdjacentEntity: placeAdjacentEntity,
stopFollowingEntity: stopFollowingEntity
}, "followEntity", followEntity), "jumpToPoint", jumpToPoint), "trackEntity", trackEntity)
}, children);
};
export var useHUDTerrain = function useHUDTerrain() {
var context = useContext(HUDTerrainContext);
if (!context) {
throw new Error("Must use within a HUDTerrainProvider");
}
return context;
};