UNPKG

@react-ecs/boids

Version:

<h1 align="center"> <br> <a href="https://react-ecs.ldlework.com"><img src="https://i.imgur.com/Rn6yLZs.gif" alt="React ECS" width="300"></a> <br> React ECS <br> <a href="https://react-ecs.ldlework.com">react-ecs.ldlework.com</a> </h1>

1,488 lines (1,273 loc) 45.6 kB
import { jsxs, Fragment, jsx } from 'react/jsx-runtime'; import { Box, Torus } from '@react-three/drei'; import { useControls } from 'leva'; import { useRef, useMemo, Suspense, forwardRef } from 'react'; import { Facet, useQuery, useSystem, Entity } from '@react-ecs/core'; import { Vector3, LineBasicMaterial, Color, BufferGeometry, Line } from 'three'; import { ThreeView } from '@react-ecs/three'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __spreadArrays() { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; } var Acceleration = /** @class */ function (_super) { __extends(Acceleration, _super); function Acceleration() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.amount = new Vector3(0, 0, 0); return _this; } return Acceleration; }(Facet); var Neighbor = /** @class */ function (_super) { __extends(Neighbor, _super); function Neighbor() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.meta = { neighbors: [] }; return _this; } return Neighbor; }(Facet); var TeleportSystem = function TeleportSystem(props) { var query = useQuery(function (e) { return e.hasAll(ThreeView, Velocity); }); return useSystem(function (dt) { query.loop([ThreeView], function (e, _a) { var view = _a[0]; var pos = view.object3d.position; if (pos.x < -props.size) { pos.setX(props.size); } else if (pos.x > props.size) { pos.setX(-props.size); } if (pos.y < -props.size) { pos.setY(props.size); } else if (pos.y > props.size) { pos.setY(-props.size); } if (pos.z < -props.size) { pos.setZ(props.size); } else if (pos.z > props.size) { pos.setZ(-props.size); } }); }); }; var Teleporter = function Teleporter(props) { return jsxs(Fragment, { children: [jsx(TeleportSystem, { size: props.size }, void 0), props.showBounds && jsxs(Fragment, { children: [jsx(Box, { scale: 3 }, void 0), jsx(Box, { position: [props.size, props.size, props.size] }, void 0), jsx(Box, { position: [-props.size, -props.size, -props.size] }, void 0), jsx(Box, { position: [props.size, -props.size, props.size] }, void 0), jsx(Box, { position: [-props.size, props.size, -props.size] }, void 0), jsx(Box, { position: [props.size, props.size, -props.size] }, void 0), jsx(Box, { position: [-props.size, -props.size, props.size] }, void 0), jsx(Box, { position: [props.size, -props.size, -props.size] }, void 0), jsx(Box, { position: [-props.size, props.size, props.size] }, void 0)] }, void 0)] }, void 0); }; var Tracker = /** @class */ function (_super) { __extends(Tracker, _super); function Tracker() { return _super !== null && _super.apply(this, arguments) || this; } return Tracker; }(Facet); Tracker.__componentClassId__ = 99; var Velocity = /** @class */ function (_super) { __extends(Velocity, _super); function Velocity() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.amount = new Vector3(Math.random() - .5, Math.random() - .5, Math.random() - .5); return _this; } return Velocity; }(Facet); var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var check = function (it) { return it && it.Math == Math && it; }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global_1 = // eslint-disable-next-line es/no-global-this -- safe check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func -- fallback (function () { return this; })() || Function('return this')(); var fails = function (exec) { try { return !!exec(); } catch (error) { return true; } }; // Detect IE8's incomplete defineProperty implementation var descriptors = !fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- required for testing return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; }); var $propertyIsEnumerable = {}.propertyIsEnumerable; // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // Nashorn ~ JDK8 bug var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1); // `Object.prototype.propertyIsEnumerable` method implementation // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable var f = NASHORN_BUG ? function propertyIsEnumerable(V) { var descriptor = getOwnPropertyDescriptor(this, V); return !!descriptor && descriptor.enumerable; } : $propertyIsEnumerable; var objectPropertyIsEnumerable = { f: f }; var createPropertyDescriptor = function (bitmap, value) { return { enumerable: !(bitmap & 1), configurable: !(bitmap & 2), writable: !(bitmap & 4), value: value }; }; var toString = {}.toString; var classofRaw = function (it) { return toString.call(it).slice(8, -1); }; var split = ''.split; // fallback for non-array-like ES3 and non-enumerable old V8 strings var indexedObject = fails(function () { // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 // eslint-disable-next-line no-prototype-builtins -- safe return !Object('z').propertyIsEnumerable(0); }) ? function (it) { return classofRaw(it) == 'String' ? split.call(it, '') : Object(it); } : Object; // `RequireObjectCoercible` abstract operation // https://tc39.es/ecma262/#sec-requireobjectcoercible var requireObjectCoercible = function (it) { if (it == undefined) throw TypeError("Can't call method on " + it); return it; }; // toObject with fallback for non-array-like ES3 strings var toIndexedObject = function (it) { return indexedObject(requireObjectCoercible(it)); }; var isObject = function (it) { return typeof it === 'object' ? it !== null : typeof it === 'function'; }; // `ToPrimitive` abstract operation // https://tc39.es/ecma262/#sec-toprimitive // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string var toPrimitive = function (input, PREFERRED_STRING) { if (!isObject(input)) return input; var fn, val; if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; throw TypeError("Can't convert object to primitive value"); }; var hasOwnProperty = {}.hasOwnProperty; var has = function (it, key) { return hasOwnProperty.call(it, key); }; var document = global_1.document; // typeof document.createElement is 'object' in old IE var EXISTS = isObject(document) && isObject(document.createElement); var documentCreateElement = function (it) { return EXISTS ? document.createElement(it) : {}; }; // Thank's IE8 for his funny defineProperty var ie8DomDefine = !descriptors && !fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- requied for testing return Object.defineProperty(documentCreateElement('div'), 'a', { get: function () { return 7; } }).a != 7; }); // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // `Object.getOwnPropertyDescriptor` method // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor var f$1 = descriptors ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { O = toIndexedObject(O); P = toPrimitive(P, true); if (ie8DomDefine) try { return $getOwnPropertyDescriptor(O, P); } catch (error) { /* empty */ } if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]); }; var objectGetOwnPropertyDescriptor = { f: f$1 }; var anObject = function (it) { if (!isObject(it)) { throw TypeError(String(it) + ' is not an object'); } return it; }; // eslint-disable-next-line es/no-object-defineproperty -- safe var $defineProperty = Object.defineProperty; // `Object.defineProperty` method // https://tc39.es/ecma262/#sec-object.defineproperty var f$2 = descriptors ? $defineProperty : function defineProperty(O, P, Attributes) { anObject(O); P = toPrimitive(P, true); anObject(Attributes); if (ie8DomDefine) try { return $defineProperty(O, P, Attributes); } catch (error) { /* empty */ } if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); if ('value' in Attributes) O[P] = Attributes.value; return O; }; var objectDefineProperty = { f: f$2 }; var createNonEnumerableProperty = descriptors ? function (object, key, value) { return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); } : function (object, key, value) { object[key] = value; return object; }; var setGlobal = function (key, value) { try { createNonEnumerableProperty(global_1, key, value); } catch (error) { global_1[key] = value; } return value; }; var SHARED = '__core-js_shared__'; var store = global_1[SHARED] || setGlobal(SHARED, {}); var sharedStore = store; var functionToString = Function.toString; // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper if (typeof sharedStore.inspectSource != 'function') { sharedStore.inspectSource = function (it) { return functionToString.call(it); }; } var inspectSource = sharedStore.inspectSource; var WeakMap = global_1.WeakMap; var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap)); var shared = createCommonjsModule(function (module) { (module.exports = function (key, value) { return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); })('versions', []).push({ version: '3.10.2', mode: 'global', copyright: '© 2021 Denis Pushkarev (zloirock.ru)' }); }); var id = 0; var postfix = Math.random(); var uid = function (key) { return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36); }; var keys = shared('keys'); var sharedKey = function (key) { return keys[key] || (keys[key] = uid(key)); }; var hiddenKeys = {}; var OBJECT_ALREADY_INITIALIZED = 'Object already initialized'; var WeakMap$1 = global_1.WeakMap; var set, get, has$1; var enforce = function (it) { return has$1(it) ? get(it) : set(it, {}); }; var getterFor = function (TYPE) { return function (it) { var state; if (!isObject(it) || (state = get(it)).type !== TYPE) { throw TypeError('Incompatible receiver, ' + TYPE + ' required'); } return state; }; }; if (nativeWeakMap) { var store$1 = sharedStore.state || (sharedStore.state = new WeakMap$1()); var wmget = store$1.get; var wmhas = store$1.has; var wmset = store$1.set; set = function (it, metadata) { if (wmhas.call(store$1, it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED); metadata.facade = it; wmset.call(store$1, it, metadata); return metadata; }; get = function (it) { return wmget.call(store$1, it) || {}; }; has$1 = function (it) { return wmhas.call(store$1, it); }; } else { var STATE = sharedKey('state'); hiddenKeys[STATE] = true; set = function (it, metadata) { if (has(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED); metadata.facade = it; createNonEnumerableProperty(it, STATE, metadata); return metadata; }; get = function (it) { return has(it, STATE) ? it[STATE] : {}; }; has$1 = function (it) { return has(it, STATE); }; } var internalState = { set: set, get: get, has: has$1, enforce: enforce, getterFor: getterFor }; var redefine = createCommonjsModule(function (module) { var getInternalState = internalState.get; var enforceInternalState = internalState.enforce; var TEMPLATE = String(String).split('String'); (module.exports = function (O, key, value, options) { var unsafe = options ? !!options.unsafe : false; var simple = options ? !!options.enumerable : false; var noTargetGet = options ? !!options.noTargetGet : false; var state; if (typeof value == 'function') { if (typeof key == 'string' && !has(value, 'name')) { createNonEnumerableProperty(value, 'name', key); } state = enforceInternalState(value); if (!state.source) { state.source = TEMPLATE.join(typeof key == 'string' ? key : ''); } } if (O === global_1) { if (simple) O[key] = value; else setGlobal(key, value); return; } else if (!unsafe) { delete O[key]; } else if (!noTargetGet && O[key]) { simple = true; } if (simple) O[key] = value; else createNonEnumerableProperty(O, key, value); // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative })(Function.prototype, 'toString', function toString() { return typeof this == 'function' && getInternalState(this).source || inspectSource(this); }); }); var path = global_1; var aFunction = function (variable) { return typeof variable == 'function' ? variable : undefined; }; var getBuiltIn = function (namespace, method) { return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace]) : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; }; var ceil = Math.ceil; var floor = Math.floor; // `ToInteger` abstract operation // https://tc39.es/ecma262/#sec-tointeger var toInteger = function (argument) { return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument); }; var min = Math.min; // `ToLength` abstract operation // https://tc39.es/ecma262/#sec-tolength var toLength = function (argument) { return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 }; var max = Math.max; var min$1 = Math.min; // Helper for a popular repeating case of the spec: // Let integer be ? ToInteger(index). // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). var toAbsoluteIndex = function (index, length) { var integer = toInteger(index); return integer < 0 ? max(integer + length, 0) : min$1(integer, length); }; // `Array.prototype.{ indexOf, includes }` methods implementation var createMethod = function (IS_INCLUDES) { return function ($this, el, fromIndex) { var O = toIndexedObject($this); var length = toLength(O.length); var index = toAbsoluteIndex(fromIndex, length); var value; // Array#includes uses SameValueZero equality algorithm // eslint-disable-next-line no-self-compare -- NaN check if (IS_INCLUDES && el != el) while (length > index) { value = O[index++]; // eslint-disable-next-line no-self-compare -- NaN check if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not } else for (;length > index; index++) { if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; } return !IS_INCLUDES && -1; }; }; var arrayIncludes = { // `Array.prototype.includes` method // https://tc39.es/ecma262/#sec-array.prototype.includes includes: createMethod(true), // `Array.prototype.indexOf` method // https://tc39.es/ecma262/#sec-array.prototype.indexof indexOf: createMethod(false) }; var indexOf = arrayIncludes.indexOf; var objectKeysInternal = function (object, names) { var O = toIndexedObject(object); var i = 0; var result = []; var key; for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key); // Don't enum bug & hidden keys while (names.length > i) if (has(O, key = names[i++])) { ~indexOf(result, key) || result.push(key); } return result; }; // IE8- don't enum bug keys var enumBugKeys = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype'); // `Object.getOwnPropertyNames` method // https://tc39.es/ecma262/#sec-object.getownpropertynames // eslint-disable-next-line es/no-object-getownpropertynames -- safe var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { return objectKeysInternal(O, hiddenKeys$1); }; var objectGetOwnPropertyNames = { f: f$3 }; // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe var f$4 = Object.getOwnPropertySymbols; var objectGetOwnPropertySymbols = { f: f$4 }; // all object keys, includes non-enumerable and symbols var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { var keys = objectGetOwnPropertyNames.f(anObject(it)); var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys; }; var copyConstructorProperties = function (target, source) { var keys = ownKeys(source); var defineProperty = objectDefineProperty.f; var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); } }; var replacement = /#|\.prototype\./; var isForced = function (feature, detection) { var value = data[normalize(feature)]; return value == POLYFILL ? true : value == NATIVE ? false : typeof detection == 'function' ? fails(detection) : !!detection; }; var normalize = isForced.normalize = function (string) { return String(string).replace(replacement, '.').toLowerCase(); }; var data = isForced.data = {}; var NATIVE = isForced.NATIVE = 'N'; var POLYFILL = isForced.POLYFILL = 'P'; var isForced_1 = isForced; var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f; /* options.target - name of the target object options.global - target is the global object options.stat - export as static methods of target options.proto - export as prototype methods of target options.real - real prototype method for the `pure` version options.forced - export even if the native feature is available options.bind - bind methods to the target, required for the `pure` version options.wrap - wrap constructors to preventing global pollution, required for the `pure` version options.unsafe - use the simple assignment of property instead of delete + defineProperty options.sham - add a flag to not completely full polyfills options.enumerable - export as enumerable property options.noTargetGet - prevent calling a getter on target */ var _export = function (options, source) { var TARGET = options.target; var GLOBAL = options.global; var STATIC = options.stat; var FORCED, target, key, targetProperty, sourceProperty, descriptor; if (GLOBAL) { target = global_1; } else if (STATIC) { target = global_1[TARGET] || setGlobal(TARGET, {}); } else { target = (global_1[TARGET] || {}).prototype; } if (target) for (key in source) { sourceProperty = source[key]; if (options.noTargetGet) { descriptor = getOwnPropertyDescriptor$1(target, key); targetProperty = descriptor && descriptor.value; } else targetProperty = target[key]; FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); // contained in target if (!FORCED && targetProperty !== undefined) { if (typeof sourceProperty === typeof targetProperty) continue; copyConstructorProperties(sourceProperty, targetProperty); } // add a flag to not completely full polyfills if (options.sham || (targetProperty && targetProperty.sham)) { createNonEnumerableProperty(sourceProperty, 'sham', true); } // extend global redefine(target, key, sourceProperty, options); } }; var quot = /"/g; // B.2.3.2.1 CreateHTML(string, tag, attribute, value) // https://tc39.es/ecma262/#sec-createhtml var createHtml = function (string, tag, attribute, value) { var S = String(requireObjectCoercible(string)); var p1 = '<' + tag; if (attribute !== '') p1 += ' ' + attribute + '="' + String(value).replace(quot, '&quot;') + '"'; return p1 + '>' + S + '</' + tag + '>'; }; // check the existence of a method, lowercase // of a tag and escaping quotes in arguments var stringHtmlForced = function (METHOD_NAME) { return fails(function () { var test = ''[METHOD_NAME]('"'); return test !== test.toLowerCase() || test.split('"').length > 3; }); }; // `String.prototype.sub` method // https://tc39.es/ecma262/#sec-string.prototype.sub _export({ target: 'String', proto: true, forced: stringHtmlForced('sub') }, { sub: function sub() { return createHtml(this, 'sub', '', ''); } }); var AlignSystem = function AlignSystem(props) { var query = useQuery(function (e) { return e.hasAll(Neighbor, Velocity, Acceleration); }); return useSystem(function (dt) { query.loop([Neighbor, Velocity, Acceleration], function (e, _a) { var neighbor = _a[0], velocity = _a[1], acceleration = _a[2]; var steering = new Vector3(0, 0, 0); var neighbors = neighbor.meta.neighbors; for (var _i = 0, _b = neighbor.meta.neighbors; _i < _b.length; _i++) { var other = _b[_i]; var otherVelocity = other.get(Velocity).amount; steering.add(otherVelocity); } if (neighbors.length) { steering.divideScalar(neighbors.length); steering.sub(velocity.amount); steering.clampLength(props.min || 0, props.max || 1); } acceleration.amount = steering.normalize().clone().multiplyScalar(props.amount); }); }); }; var CohesionSystem = function CohesionSystem(props) { var query = useQuery(function (e) { return e.hasAll(ThreeView, Velocity, Neighbor); }); return useSystem(function (dt) { query.loop([ThreeView, Neighbor, Velocity, Acceleration], function (e, _a) { var view = _a[0], neighbor = _a[1], velocity = _a[2], acceleration = _a[3]; // current boid var o3d = view.object3d; var steering = new Vector3(); var neighbors = neighbor.meta.neighbors; for (var _i = 0, neighbors_1 = neighbors; _i < neighbors_1.length; _i++) { var other = neighbors_1[_i]; steering.add(other.get(ThreeView).object3d.position); } if (neighbors.length) { steering.divideScalar(neighbors.length); steering.sub(o3d.position); steering.setLength(1); steering.sub(velocity.amount); steering.clampLength(props.min, props.max); steering.multiplyScalar(props.amount); } acceleration.amount.add(steering); }); }); }; var MoveSystem = function MoveSystem(props) { var query = useQuery(function (e) { return e.hasAll(ThreeView, Velocity, Acceleration); }); return useSystem(function (dt) { query === null || query === void 0 ? void 0 : query.loop([ThreeView, Velocity, Acceleration], function (e, _a) { var view = _a[0], velocity = _a[1], acceleration = _a[2]; var transform = view.object3d; if (velocity.amount.length() > 0) { var lookPos = transform.position.clone().add(velocity.amount); transform.lookAt(lookPos); } var newPosition = transform.position.clone().add(velocity.amount.clone().multiplyScalar(dt)); velocity.amount.add(acceleration.amount); velocity.amount.clampLength(props.min, props.max); transform.position.copy(newPosition); }); }); }; var aFunction$1 = function (it) { if (typeof it != 'function') { throw TypeError(String(it) + ' is not a function'); } return it; }; // optional / simple context binding var functionBindContext = function (fn, that, length) { aFunction$1(fn); if (that === undefined) return fn; switch (length) { case 0: return function () { return fn.call(that); }; case 1: return function (a) { return fn.call(that, a); }; case 2: return function (a, b) { return fn.call(that, a, b); }; case 3: return function (a, b, c) { return fn.call(that, a, b, c); }; } return function (/* ...args */) { return fn.apply(that, arguments); }; }; // `ToObject` abstract operation // https://tc39.es/ecma262/#sec-toobject var toObject = function (argument) { return Object(requireObjectCoercible(argument)); }; // `IsArray` abstract operation // https://tc39.es/ecma262/#sec-isarray // eslint-disable-next-line es/no-array-isarray -- safe var isArray = Array.isArray || function isArray(arg) { return classofRaw(arg) == 'Array'; }; var engineIsNode = classofRaw(global_1.process) == 'process'; var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; var process = global_1.process; var versions = process && process.versions; var v8 = versions && versions.v8; var match, version; if (v8) { match = v8.split('.'); version = match[0] + match[1]; } else if (engineUserAgent) { match = engineUserAgent.match(/Edge\/(\d+)/); if (!match || match[1] >= 74) { match = engineUserAgent.match(/Chrome\/(\d+)/); if (match) version = match[1]; } } var engineV8Version = version && +version; // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { // eslint-disable-next-line es/no-symbol -- required for testing return !Symbol.sham && // Chrome 38 Symbol has incorrect toString conversion // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41); }); /* eslint-disable es/no-symbol -- required for testing */ var useSymbolAsUid = nativeSymbol && !Symbol.sham && typeof Symbol.iterator == 'symbol'; var WellKnownSymbolsStore = shared('wks'); var Symbol$1 = global_1.Symbol; var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; var wellKnownSymbol = function (name) { if (!has(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { if (nativeSymbol && has(Symbol$1, name)) { WellKnownSymbolsStore[name] = Symbol$1[name]; } else { WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); } } return WellKnownSymbolsStore[name]; }; var SPECIES = wellKnownSymbol('species'); // `ArraySpeciesCreate` abstract operation // https://tc39.es/ecma262/#sec-arrayspeciescreate var arraySpeciesCreate = function (originalArray, length) { var C; if (isArray(originalArray)) { C = originalArray.constructor; // cross-realm fallback if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; else if (isObject(C)) { C = C[SPECIES]; if (C === null) C = undefined; } } return new (C === undefined ? Array : C)(length === 0 ? 0 : length); }; var push = [].push; // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation var createMethod$1 = function (TYPE) { var IS_MAP = TYPE == 1; var IS_FILTER = TYPE == 2; var IS_SOME = TYPE == 3; var IS_EVERY = TYPE == 4; var IS_FIND_INDEX = TYPE == 6; var IS_FILTER_OUT = TYPE == 7; var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; return function ($this, callbackfn, that, specificCreate) { var O = toObject($this); var self = indexedObject(O); var boundFunction = functionBindContext(callbackfn, that, 3); var length = toLength(self.length); var index = 0; var create = specificCreate || arraySpeciesCreate; var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_OUT ? create($this, 0) : undefined; var value, result; for (;length > index; index++) if (NO_HOLES || index in self) { value = self[index]; result = boundFunction(value, index, O); if (TYPE) { if (IS_MAP) target[index] = result; // map else if (result) switch (TYPE) { case 3: return true; // some case 5: return value; // find case 6: return index; // findIndex case 2: push.call(target, value); // filter } else switch (TYPE) { case 4: return false; // every case 7: push.call(target, value); // filterOut } } } return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target; }; }; var arrayIteration = { // `Array.prototype.forEach` method // https://tc39.es/ecma262/#sec-array.prototype.foreach forEach: createMethod$1(0), // `Array.prototype.map` method // https://tc39.es/ecma262/#sec-array.prototype.map map: createMethod$1(1), // `Array.prototype.filter` method // https://tc39.es/ecma262/#sec-array.prototype.filter filter: createMethod$1(2), // `Array.prototype.some` method // https://tc39.es/ecma262/#sec-array.prototype.some some: createMethod$1(3), // `Array.prototype.every` method // https://tc39.es/ecma262/#sec-array.prototype.every every: createMethod$1(4), // `Array.prototype.find` method // https://tc39.es/ecma262/#sec-array.prototype.find find: createMethod$1(5), // `Array.prototype.findIndex` method // https://tc39.es/ecma262/#sec-array.prototype.findIndex findIndex: createMethod$1(6), // `Array.prototype.filterOut` method // https://github.com/tc39/proposal-array-filtering filterOut: createMethod$1(7) }; var arrayMethodIsStrict = function (METHOD_NAME, argument) { var method = [][METHOD_NAME]; return !!method && fails(function () { // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing method.call(null, argument || function () { throw 1; }, 1); }); }; var $forEach = arrayIteration.forEach; var STRICT_METHOD = arrayMethodIsStrict('forEach'); // `Array.prototype.forEach` method implementation // https://tc39.es/ecma262/#sec-array.prototype.foreach var arrayForEach = !STRICT_METHOD ? function forEach(callbackfn /* , thisArg */) { return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); // eslint-disable-next-line es/no-array-prototype-foreach -- safe } : [].forEach; // `Array.prototype.forEach` method // https://tc39.es/ecma262/#sec-array.prototype.foreach // eslint-disable-next-line es/no-array-prototype-foreach -- safe _export({ target: 'Array', proto: true, forced: [].forEach != arrayForEach }, { forEach: arrayForEach }); var SPECIES$1 = wellKnownSymbol('species'); var arrayMethodHasSpeciesSupport = function (METHOD_NAME) { // We can't use this feature detection in V8 since it causes // deoptimization and serious performance degradation // https://github.com/zloirock/core-js/issues/677 return engineV8Version >= 51 || !fails(function () { var array = []; var constructor = array.constructor = {}; constructor[SPECIES$1] = function () { return { foo: 1 }; }; return array[METHOD_NAME](Boolean).foo !== 1; }); }; var $map = arrayIteration.map; var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('map'); // `Array.prototype.map` method // https://tc39.es/ecma262/#sec-array.prototype.map // with adding support of @@species _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, { map: function map(callbackfn /* , thisArg */) { return $map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); } }); // iterable DOM collections // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods var domIterables = { CSSRuleList: 0, CSSStyleDeclaration: 0, CSSValueList: 0, ClientRectList: 0, DOMRectList: 0, DOMStringList: 0, DOMTokenList: 1, DataTransferItemList: 0, FileList: 0, HTMLAllCollection: 0, HTMLCollection: 0, HTMLFormElement: 0, HTMLSelectElement: 0, MediaList: 0, MimeTypeArray: 0, NamedNodeMap: 0, NodeList: 1, PaintRequestList: 0, Plugin: 0, PluginArray: 0, SVGLengthList: 0, SVGNumberList: 0, SVGPathSegList: 0, SVGPointList: 0, SVGStringList: 0, SVGTransformList: 0, SourceBufferList: 0, StyleSheetList: 0, TextTrackCueList: 0, TextTrackList: 0, TouchList: 0 }; for (var COLLECTION_NAME in domIterables) { var Collection = global_1[COLLECTION_NAME]; var CollectionPrototype = Collection && Collection.prototype; // some Chrome versions have non-configurable methods on DOMTokenList if (CollectionPrototype && CollectionPrototype.forEach !== arrayForEach) try { createNonEnumerableProperty(CollectionPrototype, 'forEach', arrayForEach); } catch (error) { CollectionPrototype.forEach = arrayForEach; } } var NeighborDebugger = /** @class */ function (_super) { __extends(NeighborDebugger, _super); function NeighborDebugger() { return _super !== null && _super.apply(this, arguments) || this; } return NeighborDebugger; }(Facet); var material = new LineBasicMaterial({ color: new Color(Math.random(), Math.random(), Math.random()) }); var zeroPoint = new Vector3(); var zeroLine = [zeroPoint, zeroPoint]; var LinePool = /** @class */ function () { function LinePool() { this.pool = []; } LinePool.prototype.fetch = function (parent, v1, v2) { if (this.pool.length) { var line = this.pool.pop(); line.geometry.setFromPoints([v1, v2]); parent.attach(line); return line; } else { var points = [v1, v2]; var geometry = new BufferGeometry(); var line = new Line(geometry, material); line.geometry.setFromPoints(points); parent.attach(line); return line; } }; LinePool.prototype.reset = function (line) { var vec = new Vector3(); line.parent.remove(line); line.position.set(0, 0, 0); line.geometry.setFromPoints(zeroLine); this.pool.push(line); }; return LinePool; }(); var NeighborDebugSystem = function NeighborDebugSystem(props) { var _a; var id = 0; var pool = useRef(new LinePool()); var targetQuery = useQuery(function (e) { return e.hasAll(ThreeView, Neighbor); }); var debugQuery = useQuery(function (e) { return e.hasAll(ThreeView, NeighborDebugger); }); var create = function create(target) { var key = id++; var targetView = target.get(ThreeView); var targetNeighorhood = target.get(Neighbor); if (!targetView) return null; return jsxs(Entity, { children: [jsx(NeighborDebugger, { targetView: targetView, targetNeighorhood: targetNeighorhood }, void 0), jsx(ThreeView, { children: jsx("group", { position: targetView.object3d.position }, void 0) }, void 0)] }, key); }; useSystem(function (dt) { debugQuery.loop([ThreeView, NeighborDebugger], function (e, _a) { var view = _a[0], debug = _a[1]; var debugObj = view.object3d; var targetObj = debug.targetView.object3d; var children = __spreadArrays(debugObj.children); for (var _i = 0, _b = debug.targetNeighorhood.meta.neighbors; _i < _b.length; _i++) { var neighbor = _b[_i]; var neighborPosition = neighbor.get(ThreeView).object3d.position; var oldLine = children.pop(); if (oldLine) { oldLine.geometry.setFromPoints([targetObj.position, neighborPosition]); } else { pool.current.fetch(debugObj, targetObj.position, neighborPosition); } } children.forEach(function (c) { return pool.current.reset(c); }); }); }); return ((_a = targetQuery.entities) === null || _a === void 0 ? void 0 : _a.map(create)) || null; }; var $filter = arrayIteration.filter; var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport('filter'); // `Array.prototype.filter` method // https://tc39.es/ecma262/#sec-array.prototype.filter // with adding support of @@species _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, { filter: function filter(callbackfn /* , thisArg */) { return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); } }); var test = []; var nativeSort = test.sort; // IE8- var FAILS_ON_UNDEFINED = fails(function () { test.sort(undefined); }); // V8 bug var FAILS_ON_NULL = fails(function () { test.sort(null); }); // Old WebKit var STRICT_METHOD$1 = arrayMethodIsStrict('sort'); var FORCED = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$1; // `Array.prototype.sort` method // https://tc39.es/ecma262/#sec-array.prototype.sort _export({ target: 'Array', proto: true, forced: FORCED }, { sort: function sort(comparefn) { return comparefn === undefined ? nativeSort.call(toObject(this)) : nativeSort.call(toObject(this), aFunction$1(comparefn)); } }); var NeighborSystem = function NeighborSystem(props) { var query = useQuery(function (e) { return e.hasAll(ThreeView, Neighbor); }); return useSystem(function (dt) { query.loop([ThreeView, Neighbor], function (e, _a) { var view = _a[0], neighbor = _a[1]; // current boid var o3d = view.object3d; // helpers var objFor = function objFor(entity) { return entity.get(ThreeView).object3d; }; var distTo = function distTo(entity) { return o3d.position.distanceTo(objFor(entity).position); }; // store current neighbors on Neighbor facet // will be used by aligntment, cohesion and avoidance systems neighbor.meta.neighbors = query.entities.filter(function (_e) { return _e.id !== e.id; }).filter(function (_e) { return props.filter ? props.filter(e, _e) : true; }).filter(function (_e) { return distTo(_e) < props.radius; }).sort(function (a, b) { return distTo(a) - distTo(b); }); }); }); }; var SeparationSystem = function SeparationSystem(props) { var query = useQuery(function (e) { return e.hasAll(ThreeView, Velocity, Neighbor); }); return useSystem(function (dt) { query.loop([ThreeView, Neighbor, Velocity, Acceleration], function (e, _a) { var view = _a[0], neighbor = _a[1], velocity = _a[2], acceleration = _a[3]; // current boid var o3d = view.object3d; var steering = new Vector3(); var neighbors = neighbor.meta.neighbors; for (var _i = 0, neighbors_1 = neighbors; _i < neighbors_1.length; _i++) { var other = neighbors_1[_i]; var otherPosition = other.get(ThreeView).object3d.position; var dist = o3d.position.distanceTo(otherPosition); var diff = o3d.position.clone().sub(otherPosition); diff.divideScalar(dist * dist); steering.add(diff); } if (neighbors.length) { steering.divideScalar(neighbors.length); steering.sub(velocity.amount); steering.clampLength(props.min, props.max); steering.multiplyScalar(props.amount); } acceleration.amount.add(steering); }); }); }; var BoidSim = function BoidSim(props) { var _a = useControls('sim', { size: { value: 100, min: 20, max: 200 }, count: { value: 250, min: 1, max: 250 }, spawnHeight: { value: 1, min: 0, max: 1 }, neighborRadius: { value: 10, min: 1, max: 50 }, showBounds: false }, {}), size = _a.size, count = _a.count, spawnHeight = _a.spawnHeight, neighborRadius = _a.neighborRadius, showBounds = _a.showBounds; var alignment = useControls('alignment', { enabled: true, multiplier: { value: .1, min: 0, max: 1 }, turningRange: { value: [0, .1], min: 0, max: 1 } }); var cohesion = useControls('cohesion', { enabled: true, multiplier: { value: 1, min: 0, max: 1 }, speedRange: { value: [0, 1], min: 0, max: 10 } }); var separation = useControls('separation', { enabled: true, multiplier: { value: 2, min: 0, max: 2 }, speedRange: { value: [0, 3], min: 0, max: 10 } }); var speed = useControls('speed', { range: { value: [15, 50], min: 0, max: 50 } }); var comp = function comp() { return Math.random() * size * 2 - size; }; var pos = function pos() { return [comp(), comp() * spawnHeight, comp()]; }; var data = useMemo(function () { var items = []; for (var i = 0; i < count; i++) { items.push(jsx(Suspense, __assign({ fallback: jsx(Torus, {}, void 0) }, { children: jsx(Plane, { render: props.render, position: pos() }, void 0) }), void 0)); } return items; // eslint-disable-next-line react-hooks/exhaustive-deps }, [size, spawnHeight, count]); return jsxs(Fragment, { children: [jsx(Teleporter, { showBounds: showBounds, size: size }, void 0), jsx(NeighborSystem, { radius: neighborRadius }, void 0), jsx(AlignSystem, { amount: alignment.enabled ? alignment.multiplier : 0, min: alignment.turningRange[0], max: alignment.turningRange[1] }, void 0), jsx(CohesionSystem, { amount: cohesion.enabled ? cohesion.multiplier : 0, min: cohesion.speedRange[0], max: cohesion.speedRange[1] }, void 0), jsx(SeparationSystem, { amount: separation.enabled ? separation.multiplier : 0, min: separation.speedRange[0], max: separation.speedRange[1] }, void 0), jsx(MoveSystem, { min: speed.range[0], max: speed.range[1] }, void 0), data] }, void 0); }; var Plane = /*#__PURE__*/forwardRef(function (props, ref) { var render = props.render, groupProps = __rest(props, ["render"]); return jsxs(Entity, { children: [jsx(Neighbor, {}, void 0), jsx(Velocity, {}, void 0), jsx(Acceleration, {}, void 0), jsx(ThreeView, { children: jsx("group", __assign({ ref: ref }, groupProps, { dispose: null }, { children: render() }), void 0) }, void 0)] }, void 0); }); export { Acceleration, AlignSystem, BoidSim, CohesionSystem, MoveSystem, Neighbor, NeighborDebugSystem, NeighborSystem, Plane, SeparationSystem, TeleportSystem, Teleporter, Tracker, Velocity };