@trap_stevo/legendarybuilderproreact-ui
Version:
The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton
481 lines • 19.5 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
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$initialPositionS = _ref.initialPositionScaleFactor,
initialPositionScaleFactor = _ref$initialPositionS === void 0 ? 2 : _ref$initialPositionS,
_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 positionScaleFactor = useRef(initialPositionScaleFactor);
var entityDataRefs = useRef(new Map());
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) {
if (!entityDataRefs.current.has(entity.id)) {
var _entity$maxHealth, _entity$health;
entityDataRefs.current.set(entity.id, _objectSpread({
maxHealth: (_entity$maxHealth = entity.maxHealth) !== null && _entity$maxHealth !== void 0 ? _entity$maxHealth : 100,
health: (_entity$health = entity.health) !== null && _entity$health !== void 0 ? _entity$health : 100,
radius: entity.radius,
height: entity.height,
width: entity.width,
x: entity.x,
y: entity.y
}, 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;
});
});
entityDataRefs.current["delete"](entityID);
trackingRefs.current["delete"](entityID);
};
var updateEntityPosition = function updateEntityPosition(entityID, dx, dy) {
var data = entityDataRefs.current.get(entityID);
if (!data) {
return;
}
data.x += dx;
data.y += dy;
var callbacks = trackingRefs.current.get(entityID);
if (callbacks) {
var _iterator = _createForOfIteratorHelper(callbacks),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var callback = _step.value;
callback(entityID, _objectSpread({
id: entityID
}, data));
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
};
var updateEntityHealth = function updateEntityHealth(entityID, healthChange) {
var _data$maxHealth;
var allowOverMax = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var data = entityDataRefs.current.get(entityID);
if (!data) {
return;
}
var max = (_data$maxHealth = data.maxHealth) !== null && _data$maxHealth !== void 0 ? _data$maxHealth : 100;
var newHealth = allowOverMax ? data.health + healthChange : Math.max(0, Math.min(data.health + healthChange, max));
updateEntityData(entityID, {
health: newHealth
});
};
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 : [])));
var data = entityDataRefs.current.get(entityID);
if (!data) {
return;
}
var updated = {};
for (var key in sizeChanges) {
var _data$key, _data$key2;
if (!validSizeProperties.has(key)) {
continue;
}
var newSize = allowNegative ? ((_data$key = data[key]) !== null && _data$key !== void 0 ? _data$key : 0) + sizeChanges[key] : Math.max(0, ((_data$key2 = data[key]) !== null && _data$key2 !== void 0 ? _data$key2 : 0) + sizeChanges[key]);
updated[key] = newSize;
}
if (Object.keys(updated).length > 0) {
updateEntityData(entityID, updated);
}
};
var updateEntityData = function updateEntityData(entityID) {
var updates = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var data = entityDataRefs.current.get(entityID);
if (!data) {
return;
}
var updated = false;
for (var key in updates) {
var value = updates[key];
if (value === undefined || value === null) {
if (key in data) {
delete data[key];
updated = true;
}
} else {
if (data[key] !== value) {
data[key] = value;
updated = true;
}
}
}
if (updated) {
var callbacks = trackingRefs.current.get(entityID);
if (callbacks) {
var _iterator2 = _createForOfIteratorHelper(callbacks),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var callback = _step2.value;
callback(entityID, _objectSpread({
id: entityID
}, data));
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
}
}
};
var updateEntity = function updateEntity(entityID, newData) {
updateEntityData(entityID, newData);
setEntities(function (prev) {
return prev.map(function (e) {
if (e.id === entityID) {
var updatedEntity = _objectSpread(_objectSpread({}, e), newData);
var callbacks = trackingRefs.current.get(entityID);
if (callbacks) {
var _iterator3 = _createForOfIteratorHelper(callbacks),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var callback = _step3.value;
callback(entityID, updatedEntity);
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
}
return updatedEntity;
}
return e;
});
});
};
var getEntityPosition = function getEntityPosition(entityID) {
var data = entityDataRefs.current.get(entityID);
if (!data) {
return null;
}
return {
x: data.x,
y: data.y
};
};
var getEntityData = function getEntityData(entityID) {
var _entityDataRefs$curre;
return (_entityDataRefs$curre = entityDataRefs.current.get(entityID)) !== null && _entityDataRefs$curre !== void 0 ? _entityDataRefs$curre : null;
};
var getEntity = function getEntity(entityID) {
return entities[entityID];
};
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 * positionScaleFactor.current;
var scaledY = y * positionScaleFactor.current;
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) {
if (!trackingRefs.current.has(entityID)) {
trackingRefs.current.set(entityID, new Set());
}
trackingRefs.current.get(entityID).add(callback);
};
var untrackEntity = function untrackEntity(entityID, callback) {
var callbacks = trackingRefs.current.get(entityID);
if (!callbacks) {
return;
}
callbacks["delete"](callback);
if (callbacks.size === 0) {
trackingRefs.current["delete"](entityID);
}
};
useEffect(function () {
setZoomLimits(initialZoomLimits);
}, [JSON.stringify(initialZoomLimits)]);
useEffect(function () {
setZoom(initialZoom);
}, [initialZoom]);
useEffect(function () {
positionScaleFactor.current = initialPositionScaleFactor;
}, [initialPositionScaleFactor]);
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(_defineProperty({
registerCamera: registerCamera,
cameraPosition: cameraPosition,
cameraRef: cameraRef,
canvasRef: canvasRef,
entities: entities,
positionScaleFactor: positionScaleFactor,
setZoomLimits: setZoomLimits,
zoomLimits: zoomLimits,
setZoom: setZoom,
zoom: zoom,
visibleChunks: visibleChunks,
followEntity: followEntity,
updateEntityPosition: updateEntityPosition,
updateEntityHealth: updateEntityHealth,
updateEntitySize: updateEntitySize,
updateEntityData: updateEntityData,
updateEntity: updateEntity,
removeEntity: removeEntity,
addEntity: addEntity,
getEntityPosition: getEntityPosition,
getEntityData: getEntityData,
getEntity: getEntity,
worldToScreen: worldToScreen,
screenToWorld: screenToWorld,
updateZoomedViewBox: updateZoomedViewBox,
updateViewBox: updateViewBox,
viewBox: viewBox,
placeAdjacentEntity: placeAdjacentEntity,
stopFollowingEntity: stopFollowingEntity
}, "followEntity", followEntity), "jumpToPoint", jumpToPoint), "untrackEntity", untrackEntity), "trackEntity", trackEntity)
}, children);
};
export var useHUDTerrain = function useHUDTerrain() {
var context = useContext(HUDTerrainContext);
if (!context) {
throw new Error("Must use within a HUDTerrainProvider");
}
return context;
};