{"_id":"@beland/ecs-scene-utils","_rev":"1-603d088cf3810a3d3105287490103602","name":"@beland/ecs-scene-utils","dist-tags":{"latest":"0.0.2-dev"},"versions":{"0.0.1-dev":{"name":"@beland/ecs-scene-utils","version":"0.0.1-dev","description":"A collection of helpers to make it easier to build a Beland scene using the SDK.","main":"./dist/index.js","typings":"./dist/index.d.ts","belandLibrary":{},"scripts":{"build":"rollup -c --environment BUILD:production","make":"cp -r src dist && cp package.json dist/package.json && cp LICENSE dist/LICENSE && cp README.md dist/README.md","makeclean":"rm -rf dist && npm run make","link":"npm link && rollup --watch -c --environment BUILD:production"},"repository":{"type":"git","url":"git+https://github.com/belandproject/beland-ecs-utils.git"},"prettier":{"printWidth":80,"singleQuote":true,"semi":false},"keywords":[],"author":{"name":"Beland"},"license":"Apache-2.0","bugs":{"url":"https://github.com/belandproject/beland-ecs-utils/issues"},"homepage":"https://github.com/belandproject/beland-ecs-utils#readme","devDependencies":{"@microsoft/api-extractor":"^7.13.2","beland-ecs":"latest","glob":"^7.1.6","prettier":"^1.19.1","rollup":"^2.35.1","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-terser":"^7.0.2","rollup-plugin-typescript2":"^0.29.0","typescript":"^4.2.4"},"publishConfig":{"access":"public"},"peerDependencies":{"beland-ecs":"1.x.x"},"_id":"@beland/ecs-scene-utils@0.0.1-dev","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-bSYcP4/xwhKtUkbghexZvwmxin6mEMz2ACqgtV4bCjF0ZJSpIaeNjppUqyX/JKwQxKtZlMTxgBd0Xs07xH1+rA==","shasum":"dc520e1a4b2b2698b983a01a56d0de359171b251","tarball":"https://registry.npmjs.org/@beland/ecs-scene-utils/-/ecs-scene-utils-0.0.1-dev.tgz","fileCount":6,"unpackedSize":317411,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA/7vmEv3g2/nUQE0efpnsFP1goNFx2zxA9jY9m1kDhFAiB+Wvt3t+M8dQ8JmR8HDBnvdu++2eHXK8RWqnnTDbyRlw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJicgEEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrcDQ/9H6Zf0ltj8EvtFmmGcseRXV93nlhCmCxO5ewWrpB+8X0D0ikT\r\n+paGYgHNGg/nuy3fMJBeDEkUSQccBcm2xuLqexyxFVhqj9G5a4FpWrzACHod\r\nOyBsQ1Qx6/MkCbZmEhmrjkAsyR91FOBuIR6VT+qIPZYM1fUp1YfB2Um1LJRa\r\nHR/M0rFzgrEbTgQWv7ZNGoLkMupGZqza9aPqQS8d+cErlTXkKC64z1+l7R1f\r\nGIc/SL+x4TSk37dzYMpy3gKwt69M8rCOPgwkn5qGzy+gO0TI73t9p17YFxnM\r\n1AAI328vL8uwCK5tHASQk/Zwf5dOgu9VN1AKyn19mObjkva6ygY+GdumdjRu\r\n21o7GEr0pa2TwR29/K5sxxfgeWSKBIu9ETsHGYl4YoZkCMtPOcAYaKId6+eW\r\nodXFXoCYsuNQxUnaYrbbHSZyTEEIYHOWzRnBAjpt74dwC/LgN5ffkYHMRAYm\r\nW3HcBSSmkgzg+bgJrSdrhIluWQ4fcLjiM2POha3x81IyWw6njb+OV4X6H/56\r\nPta3V9+bESh9kkkhu/ANJlPRlDiCQLGthfZRCn6wgZJm4RtW30G4ErgsXQ0P\r\nsMqI88WUR78uJcTwt+NLDd1tTZlqfJKp1NIbbawr0sSJk4AQ6bMZX3ebl4MR\r\nwvKoUpT9l2YIurkJb8U/Zrrwc5doNhC5hqQ=\r\n=vzMK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"beland","email":"beland.developer@gmail.com"},"directories":{},"maintainers":[{"name":"beland","email":"beland.developer@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ecs-scene-utils_0.0.1-dev_1651638532712_0.07914335876315759"},"_hasShrinkwrap":false},"0.0.2-dev":{"name":"@beland/ecs-scene-utils","version":"0.0.2-dev","description":"A collection of helpers to make it easier to build a Beland scene using the SDK.","main":"./dist/index.js","typings":"./dist/index.d.ts","belandLibrary":{},"scripts":{"build":"rollup -c --environment BUILD:production","make":"cp -r src dist && cp package.json dist/package.json && cp LICENSE dist/LICENSE && cp README.md dist/README.md","makeclean":"rm -rf dist && npm run make","link":"npm link && rollup --watch -c --environment BUILD:production"},"repository":{"type":"git","url":"git+https://github.com/belandproject/beland-ecs-utils.git"},"prettier":{"printWidth":80,"singleQuote":true,"semi":false},"keywords":[],"author":{"name":"Beland"},"license":"Apache-2.0","bugs":{"url":"https://github.com/belandproject/beland-ecs-utils/issues"},"homepage":"https://github.com/belandproject/beland-ecs-utils#readme","devDependencies":{"@microsoft/api-extractor":"^7.13.2","beland-ecs":"0.0.6-dev","glob":"^7.1.6","prettier":"^1.19.1","rollup":"^2.35.1","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-terser":"^7.0.2","rollup-plugin-typescript2":"^0.29.0","typescript":"^4.2.4"},"publishConfig":{"access":"public"},"peerDependencies":{"beland-ecs":"0.0.6-dev"},"gitHead":"214aa8ab161c6b6232cca3d99d78e1a80d087df7","_id":"@beland/ecs-scene-utils@0.0.2-dev","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-F+VZuQQk4S96kdnBFasThkxgVql9V7Bm97dxba7gEQoAeiRgiV/ei17ApRlZ5N3/wx2vyOnm+UWbrzHwYvWiRA==","shasum":"28b9b95e7ab871366f8e18b57c5544d23def95d8","tarball":"https://registry.npmjs.org/@beland/ecs-scene-utils/-/ecs-scene-utils-0.0.2-dev.tgz","fileCount":6,"unpackedSize":317421,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpBYfffW8b7qSoFVzWL4y4ubYtkGtaUtT3nkqx9Kza7QIhAIy/kKT3bZDboYq8IWOYA8iYBlPep+EcNdpVwEhj1Ifg"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisHeHACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmppLg//dW2ibuTCYd16qrbsT86MiaICaDiI8c6cqZv2pYfLiJ9y3LFO\r\nS3ly3udKsAgoecreTSbYOF036+lnmLvz6jVbmI+KgYuem0LJu+D4wAJTdvZK\r\nJEj6qddB3fi9nDxjID2AdTCoRK0fYvJXlnBprPK1EKYmbuCRKugp4DEDdT1y\r\nZLUu9UgM2OSUYDyZJd5tU2LvZ52UgZ3BlNgaHVzylBOjobiXcGdpOpWNTEBc\r\nAabB4J9vz46baCASj1Uw5z3GZj5jq2eI1n2DJHauvkbYQlwubEGC/I781fUR\r\nqAxdbn/eVxN5hByi6UOwIb6v4Yl+N+MgBjB4esVkf/FP5dOP+tLos6gzdDGL\r\nWt3lEHkOiJ9U07HONTldgQZLwxPiULAGxtdxCXx8qw2N5Hi7FAyEAyNJcci2\r\nNWW/FG+c+RNWIRoLbRHt913gQcH40nhi9HFDD5cXABe+GzeoT0KLJsEeLmtU\r\nlkRyOWs8XChqeg/gPsvKLW6+gupYL4PNV5eU+CJyuJTaHaFOdEVWpip2X8EO\r\nT1wUPv+Z78A3yauJwV6Cr1MlXyn6qx9Ok2eOTJKLJuyus7v1BmIJNK58lEMO\r\nM8w4aKdWNfUeyRpwU/rv4IAP0YsPehYhLEC588Po0fZTjicUlinDC10oX0sh\r\nxN1lNjhUKdGTm04CuAetDWGJ6//uRvQ5aw8=\r\n=e5Mm\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"beland","email":"beland.developer@gmail.com"},"directories":{},"maintainers":[{"name":"beland","email":"beland.developer@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ecs-scene-utils_0.0.2-dev_1655732103111_0.2570723985151697"},"_hasShrinkwrap":false}},"time":{"created":"2022-05-04T04:28:52.599Z","0.0.1-dev":"2022-05-04T04:28:52.876Z","modified":"2022-06-20T13:35:03.433Z","0.0.2-dev":"2022-06-20T13:35:03.346Z"},"maintainers":[{"name":"beland","email":"beland.developer@gmail.com"}],"description":"A collection of helpers to make it easier to build a Beland scene using the SDK.","homepage":"https://github.com/belandproject/beland-ecs-utils#readme","keywords":[],"repository":{"type":"git","url":"git+https://github.com/belandproject/beland-ecs-utils.git"},"author":{"name":"Beland"},"bugs":{"url":"https://github.com/belandproject/beland-ecs-utils/issues"},"license":"Apache-2.0","readme":"# beland-ecs-utils\n\nThis library includes a number of helpful pre-built tools that include components, methods, and systems. They offer simple solutions to common scenarios that you're likely to run into.\n\n- [Gradual Movement](#gradual-movement)\n  - [Move an entity](#move-an-entity)\n  - [Follow a path](#follow-a-path)\n  - [Follow a curved path](#follow-a-curved-path)\n  - [Rotate an entity](#rotate-an-entity)\n  - [Sustain rotation](#sustain-rotation)\n  - [Change scale](#change-scale)\n  - [Non-linear changes](#non-linear-changes)\n  - [Callback on finish](#callback-on-finish)\n- [Toggle](#toggle)\n- [Time](#time)\n  - [Delay a function](#delay-a-function)\n  - [Delay removing an entity](#delay-removing-an-entity)\n  - [Repeat at an Interval](#repeat-at-an-interval)\n- [Triggers](#triggers)\n  - [Trigger Component](#trigger-component)\n  - [One Time Trigger](#one-time-trigger)\n  - [Trigger layers](#trigger-layers)\n- [Conversions](#conversions)\n  - [clamp](#clamp)\n  - [map](#map)\n  - [world position](#world-position)\n  - [world rotation](#world-rotation)\n- [Send requests](#send-requests)\n- [Labels](#labels)\n- [Debug helpers](#debug-helpers)\n  - [Debug cube](#debug-cube)\n- [Action sequence](#action-sequence)\n  - [IAction](#iaction)\n  - [Action Sequence Builder](#action-sequence-builder)\n  - [Action Sequence System](#action-aequence-system)\n  - [Full example](#full-example)\n\n## Using the Utils library\n\nTo use any of the helpers provided by the utils library\n\n1. Install it as an `npm` package. Run this command in your scene's project folder:\n\n```\nnpm install @beland/ecs-scene-utils -B\n```\n\n2. Run `bld start` or `bld build` so the dependencies are correctly installed.\n\n3) Import the library into the scene's script. Add this line at the start of your `game.ts` file, or any other TypeScript files that require it:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n```\n\n4. In your TypeScript file, write `utils.` and let the suggestions of your IDE show the available helpers.\n\n## Gradual Movement\n\n### Move an entity\n\nTo move an entity over a period of time, from one position to another, use the `MoveTransformComponent` component.\n\n`MoveTransformComponent` has three required arguments:\n\n- `start`: `Vector3` for the start position\n- `end`: `Vector3` for the end position\n- `duration`: duration (in seconds) of the translation\n\nThis example moves an entity from one position to another over 2 seconds:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define start and end positions\nlet StartPos = new Vector3(1, 1, 1)\nlet EndPos = new Vector3(15, 1, 15)\n\n// Move entity\nbox.addComponent(new utils.MoveTransformComponent(StartPos, EndPos, 2))\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Follow a path\n\nTo move an entity over several points of a path over a period of time, use the `FollowPathComponent` component.\n\n`FollowPathComponent` has two required arguments:\n\n- `points`: An array of `Vector3` positions that form the path.\n- `duration`: The duration (in seconds) of the whole path.\n\nThis example moves an entity over through four points over 5 seconds:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define the positions of the path\nlet path = []\npath[0] = new Vector3(1, 1, 1)\npath[1] = new Vector3(1, 1, 15)\npath[2] = new Vector3(15, 1, 15)\npath[3] = new Vector3(15, 1, 1)\n\n// Move entity\nbox.addComponent(new utils.FollowPathComponent(path, 2))\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Follow a curved path\n\nTo move an entity following a curved path over a period of time, use the `FollowCurvedPathComponent` component.\n\nThe curved path is composed of multiple straight line segments put together. You only need to supply a series of fixed path points and a smooth curve is drawn to pass through all of these.\n\n`FollowCurvedPathComponent` has three required arguments:\n\n- `points`: An array of `Vector3` positions that the curve must pass through.\n- `duration`: The duration (in seconds) of the whole path.\n- `numberOfSegments`: How many straight-line segments to use to construct the curve.\n\n> Tip: Each segment takes at least one frame to complete. Avoid using more than 30 segments per second in the duration of the path, or the entity will move significantly slower while it stops for each segment.\n\nThis example moves an entity over through a curve that's subdivided into 40 segments, over a period of 5 seconds. The curve passes through four key points.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define the positions of the path\nlet path = []\npath[0] = new Vector3(1, 1, 1)\npath[1] = new Vector3(1, 1, 15)\npath[2] = new Vector3(15, 1, 15)\npath[3] = new Vector3(15, 1, 1)\n\n// Move entity\nbox.addComponent(new utils.FollowCurvedPathComponent(path, 5, 40))\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\nThe `FollowCurvedPathComponent` also lets you set:\n\n- `turnToFaceNext`: If true, the entity will rotate on each segment of the curve to always face forward.\n- `closedCircle`: If true, traces a circle that starts back at the beginning, keeping the curvature rounded in the seams too\n\n### Rotate an entity\n\nTo rotate an entity over a period of time, from one direction to another, use the `rotateTransformComponent` component, which works very similarly to the `MoveTransformComponent` component.\n\n`rotateTransformComponent` has three required arguments:\n\n- `start`: `Quaternion` for the start rotation\n- `end`: `Quaternion` for the end rotation\n- `duration`: duration (in seconds) of the rotation\n\nThis example rotates an entity from one rotation to another over 2 seconds:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define start and end directions\nlet StartRot = Quaternion.Euler(90, 0, 0)\nlet EndRot = Quaternion.Euler(270, 0, 0)\n\n// Rotate entity\nbox.addComponent(new utils.RotateTransformComponent(StartRot, EndRot, 2))\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Sustain rotation\n\nTo rotates an entity continuously, use `KeepRotatingComponent`. The entity will keep rotating forever until it's explicitly stopped or the component is removed.\n\n`KeepRotatingComponent` has one required argument:\n\n- `rotationVelocity`: A quaternion describing the desired rotation to perform each second second. For example `Quaternion.Euler(0, 45, 0)` rotates the entity on the Y axis at a speed of 45 degrees per second, meaning that it makes a full turn every 8 seconds.\n\nThe component also contains the following method:\n\n- `stop()`: stops rotation and removes the component from any entities its added to.\n\nIn the following example, a cube rotates continuously until clicked:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform({ position: new Vector3(1, 1, 1) }))\n\n// Rotate entity\nbox.addComponent(new utils.KeepRotatingComponent(Quaternion.Euler(0, 45, 0)))\n\n// Listen for click\nbox.addComponent(\n  new OnClick(() => {\n    box.getComponent(utils.KeepRotatingComponent).stop()\n  })\n)\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Change scale\n\nTo adjust the scale of an entity over a period of time, from one size to another, use the `ScaleTransformComponent` component, which works very similarly to the `MoveTransformComponent` component.\n\n`ScaleTransformComponent` has three required arguments:\n\n- `start`: `Vector3` for the start scale\n- `end`: `Vector3` for the end scale\n- `duration`: duration (in seconds) of the scaling\n\nThis example scales an entity from one size to another over 2 seconds:\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define start and end positions\nlet StartSize = new Vector3(1, 1, 1)\nlet EndSize = new Vector3(0.75, 2, 0.75)\n\n// Move entity\nbox.addComponent(new utils.ScaleTransformComponent(StartSize, EndSize, 2))\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Non-linear changes\n\nAll of the translation components, the `MoveTransformComponent`, `rotateTransformComponent`, `ScaleTransformComponent`, and `FollowPathComponent` have an optional argument to set the rate of change. By default, the movement, rotation, or scaling occurs at a linear rate, but this can be set to other options.\n\nThe following values are accepted:\n\n- `Interpolation.LINEAR`\n- `Interpolation.EASEINQUAD`\n- `Interpolation.EASEOUTQUAD`\n- `Interpolation.EASEQUAD`\n- `Interpolation.EASEINSINE`\n- `Interpolation.EASEOUTSINE`\n- `Interpolation.EASESINE`\n- `Interpolation.EASEINEXPO`\n- `Interpolation.EASEOUTEXPO`\n- `Interpolation.EASEEXPO`\n- `Interpolation.EASEINELASTIC`\n- `Interpolation.EASEOUTELASTIC`\n- `Interpolation.EASEELASTIC`\n- `Interpolation.EASEINBOUNCE`\n- `Interpolation.EASEOUTEBOUNCE`\n- `Interpolation.EASEBOUNCE`\n\nThe following example moves a box following an ease-in rate:\n\n```ts\nbox.addComponent(\n  new utils.MoveTransformComponent(\n    StartPos,\n    EndPos,\n    2,\n    null,\n    utils.InterpolationType.EASEINQUAD\n  )\n)\n```\n\n### Callback on finish\n\nAll of the translation components, the `MoveTransformComponent`, `rotateTransformComponent`, `ScaleTransformComponent`, `FollowPathComponent`, and `FollowCurvedPathComponent` have an optional argument that executes a function when the translation is complete.\n\n- `onFinishCallback`: function to execute when movement is done.\n\nThe following example logs a message when the box finishes its movement. The example uses `MoveTransformComponent`, but the same applies to `rotateTransformComponent` and `ScaleTransformComponent`.\n\n```ts\nbox.addComponent(\n  new utils.MoveTransformComponent(StartPos, EndPos, 2, () => {\n    log('finished moving box')\n  })\n)\n```\n\nThe `FollowPathComponent` has a two optional arguments that execute functions when a section of the path is complete and when the whole path is complete.\n\n- `onFinishCallback`: function to execute when movement is complete.\n\n- `onPointReachedCallback`: function to execute when each section of the path is done.\n\nThe following example logs a messages when the box finishes each segment of the path, and another when the entire path is done.\n\n```ts\nbox.addComponent(\n  new utils.FollowPathComponent(\n    path,\n    2,\n    () => {\n      log('finished moving box')\n    },\n    () => {\n      log('finished a segment of the path')\n    }\n  )\n)\n```\n\n## Toggle\n\nUse the `ToggleComponent` to switch an entity between two possible states, running a same function on every transition.\n\nThe `ToggleComponent` has the following arguments:\n\n- `startingState`: Starting state of the toggle (ON or OFF)\n- `onValueChangedCallback`: Function to call every time the toggle state changed.\n\nIt exposes three methods:\n\n- `toggle()`: switches the state of the component between ON and OFF\n- `isOn()`: reads the current state of the component, without altering it. It returns a boolean, where `true` means ON.\n- `setCallback()`: allows you to change the function to be executed by `onValueChangedCallback`, for the next time it's toggled.\n\nThe following example switches the color of a box between two colors each time it's clicked.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define two different materials\nlet greenMaterial = new Material()\ngreenMaterial.albedoColor = Color3.Green()\nlet redMaterial = new Material()\nredMaterial.albedoColor = Color3.Red()\n\n// Add a Toggle component\nbox.addComponent(\n  new utils.ToggleComponent(utils.ToggleState.Off, value => {\n    if (value == utils.ToggleState.On) {\n      //set color to green\n      box.addComponentOrReplace(greenMaterial)\n    } else {\n      //set color to red\n      box.addComponentOrReplace(redMaterial)\n    }\n  })\n)\n\n//listen for click on the box and toggle it's state\nbox.addComponent(\n  new OnClick(event => {\n    box.getComponent(utils.ToggleComponent).toggle()\n  })\n)\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n### Combine Toggle with Translate\n\nThis example combines a toggle component with a move component to switch an entity between two positions every time it's clicked.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// Create entity\nconst box = new Entity()\n\n// Give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n//Define two positions for toggling\nlet Pos1 = new Vector3(1, 1, 1)\nlet Pos2 = new Vector3(1, 1, 2)\n\n//toggle for wine bottle\nbox.addComponent(\n  new utils.ToggleComponent(utils.ToggleState.Off, value => {\n    if (value == utils.ToggleState.On) {\n      box.addComponentOrReplace(\n        new utils.MoveTransformComponent(Pos1, Pos2, 0.5)\n      )\n    } else {\n      box.addComponentOrReplace(\n        new utils.MoveTransformComponent(Pos2, Pos1, 0.5)\n      )\n    }\n  })\n)\n\n//listen for click on the box and toggle it's state\nbox.addComponent(\n  new OnClick(event => {\n    box.getComponent(utils.ToggleComponent).toggle()\n  })\n)\n\n// Add entity to engine\nengine.addEntity(box)\n```\n\n## Time\n\nThese tools are all related to the passage of time in the scene.\n\n### Delay a function\n\nUse the `setTimeout` function to delay the execution of a function by a given amount of milliseconds.\n\nThis function requires two fields:\n\n- `ms`: How many milliseconds to delay the function\n- `callback`: The function to execute after the waiting period\n\nThis example delays the logging of a message by 1000 milliseconds.\n\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\nutils.setTimeout(1000, ()=>{\n\tlog(\"Hello World\")\n})\n```\n\nAs an alternative, you can add the `Delay` component to an entity.\n\nThis example creates an entity that only becomes visible in the scene after 10000 milliseconds (10 seconds) have passed.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// create entity\nconst easterEgg = new Entity()\n\n// give entity a shape and set invisible\nconst easterEggShape = new BoxShape()\neasterEggShape.visible = false\neasterEgg.addComponent(easterEggShape)\n\n// add a delayed function\neasterEgg.addComponent(\n  new utils.Delay(10000, () => {\n    easterEgg.getComponent(BoxShape).visible = true\n  })\n)\n\n// add entity to scene\nengine.addEntity(easterEgg)\n```\n\n\n### Delay removing an entity\n\nAdd an `ExpireIn` component to an entity to remove it from the scene after an `n` amount of milliseconds.\n\nThis example creates an entity that is removed from the scene 500 milliseconds after it's clicked.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// create entity\nconst box = new Entity()\n\n// give entity a shape\nbox.addComponent(new BoxShape())\n\n// add a function to run when clicked\nbox.addComponent(\n  new OnClick(() => {\n    box.addComponent(new utils.ExpireIn(500))\n  })\n)\n\n// add entity to scene\nengine.addEntity(box)\n```\n\n### Repeat at an Interval\n\nAdd an `Interval` component to an entity to make it execute a same function every `n` milliseconds.\n\nThis example creates an entity that changes its scale to a random size every 500 milliseconds.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n// create entity\nconst box = new Entity()\n\n// give entity a shape and transform\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform())\n\n// add a repeated function\nbox.addComponent(\n  new utils.Interval(500, () => {\n    let randomSize = Math.random()\n    box.getComponent(Transform).scale.setAll(randomSize)\n  })\n)\n\n// add entity to scene\nengine.addEntity(box)\n```\n\nTo repeat the execution of a task that isn't directly tied to any entity in the scene, create a dummy entity that only holds an `Interval` component.\n\n## Triggers\n\n### Trigger Component\n\nThe trigger component can execute whatever you want whenever the player's position or the position of a specific entity or type of entity overlaps with an area.\n\nThe `TriggerComponent` has the following arguments:\n\n- `shape`: Shape of the triggering collider area, either a cube or a sphere (`TriggerBoxShape` or `TriggerSphereShape`)\n- `data`: An object of type `TriggerData` containing several optional parameters to configure the behavior of the trigger area.\n\nThe `TriggerData` type may contain the following parameters:\n\n- `onCameraEnter`: Callback function for when the player enters the trigger area\n- `onCameraExit`: Callback function for when the player leaves the trigger area\n- `layer`: Layer of the Trigger, useful to discriminate between trigger events. You can set multiple layers by using a `|` symbol.\n- `triggeredByLayer`: Against which layers to check collisions\n- `onTriggerEnter`: Callback when an entity of a valid layer enters the trigger area\n- `onTriggerExit`: Callback function for when an entity of a valid layer leaves the trigger area\n- `enableDebug`: When true, makes the trigger area visible for debug purposes. Only visible when running a preview locally, not in production.\n\nThe following example creates a trigger that changes its position randomly when triggered by the player.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n//create entity\nconst box = new Entity()\n\n//create shape for entity and disable its collision\nbox.addComponent(new BoxShape())\nbox.getComponent(BoxShape).withCollisions = false\n\n//set transform component with initial position\nbox.addComponent(new Transform({ position: new Vector3(2, 1, 2) }))\n\n// create trigger area object, setting size and relative position\nlet triggerBox = new utils.TriggerBoxShape()\n\n//create trigger for entity\nbox.addComponent(\n  new utils.TriggerComponent(\n    triggerBox, //shape\n\t{\n\t\tonCameraEnter :() => {\n\t\t\tlog('triggered!')\n\t\t\tbox.getComponent(Transform).position = new Vector3(\n\t\t\t\t1 + Math.random() * 14,\n\t\t\t\t0,\n\t\t\t\t1 + Math.random() * 14\n\t\t\t\t\t)\n\t\t}\n\t\n\t}\n    \n  )\n)\n\n//add entity to engine\nengine.addEntity(box)\n```\n\n> Note: The trigger shape can be positioned or stretched, but it can't be rotated on any axis. This is a design decision taken for performance reasons. To cover a slanted area, we recommend adding multiple triggers if applicable.\n\nEach trigger area has a shape for its area to check for collisions, which is completely independent of the visible shape of the entity. The shape of the area can either be determined by a `TriggerBoxShape` or a `TriggerSphereShape`. When instancing these, can set the scale and an offset position. By default, the trigger shape starts in the same position as the entity that has the `TriggerComponent`.\n\nYou can check where exactly the trigger area is and its scale by setting the `enableDebug` flag to true. You will then see this shape in the scene when running a preview. This debug shape is only visible in the context of a preview, not once the scene is deployed.\n\n> Note: The player's head needs to go into the trigger area to activate it. If only a player's feet or torso are in, that won't trigger it. Setting `enableDebug` to true can help you check how the area overlaps with the player.\n\n### Dissable a collision component\n\n`TriggerComponent` components have an `enabled` property, which is set to `true` by default when creating it. You can use this property to disable the behavior of the component without removing it.\n\n```TypeScript\nbox.getComponent(utils.TriggerComponent).enabled = false\n```\n\n### One Time Trigger\n\nAs a shortcut for creating a trigger area that is only actioned when the player first walks in or out, use the `addOneTimeTrigger()` function.\n\nThis function creates a new entity with a `TriggerComponent`, that gets removed as soon as the `onCameraEnter` and `onCameraExit` functions are triggered once. If only one of these is present, the entity is removed as soon it is triggered.\n\nThis function is especially useful for optimizing the loading of a scene, so that certain elements aren't loaded till a player walks into an area.\n\nThis function takes similar arguments to creating a Trigger component:\n\n- `shape`: Shape of the triggering collider area, either a cube or a sphere (`TriggerBoxShape` or `TriggerSphereShape`)\n- `data`: An object of type `TriggerData` containing several optional parameters to configure the behavior of the trigger area.\n- `parent`: An entity to set as parent of the entity created by this function. The new entity inherits position, rotation and scale from the parent.\n\nThe `TriggerData` type may contain the following parameters:\n\n- `onCameraEnter`: Callback function for when the player first enters the trigger area\n- `onCameraExit`: Callback function for when the player first leaves the trigger area\n- `enableDebug`: When true, makes the trigger area visible for debug purposes. Only visible when running a preview locally, not in production.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\nlet triggerBox = new utils.TriggerBoxShape(new Vector3(3,3,3), new Vector3(8, 1, 8))\n\nutils.addOneTimeTrigger(triggerBox, {\n\tonCameraEnter : () => {\n\t\tlog('Welcome!')\n\t},\n\tonCameraExit: ()=>{\n\t\tlog('Have a nice day!')\n\t}\n})\n```\n\nIn the example above, the trigger area will only display the welcome message the first time the player walks in, and only display the goodbye message the first time the player leaves. After that, the entity is removed from the scene.\n\n\n### Set a custom shape for player\n\nYou can optionally configure a custom shape and size for the player's trigger area, according to your needs:\n\n```ts\nutils.TriggerSystem.instance.setCameraTriggerShape(\n  new utils.TriggerBoxShape(\n    new Vector3(0.5, 1.8, 0.5),\n    new Vector3(0, -0.91, 0)\n  )\n)\n```\n\nChanging this configuration affects the behavior of all `onCameraEnter` and `onCameraExit` functions of all TriggerComponents in the scene.\n\n### Trigger layers\n\nYou can define different layers (bitwise) for triggers, and set which other layers can trigger it.\n\nThe following example creates a scene that has:\n\n- food (cones)\n- mice (spheres)\n- cats (boxes)\n\nFood is triggered (or eaten) by both cats or mice. Also, mice are eaten by cats, so a mouse's trigger area is triggered by only cats.\n\nCats and mice always move towards the food. When food or mice are eaten, they respawn in a random location.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n//define layers\nconst foodLayer = 1\nconst mouseLayer = 2\nconst catLayer = 4\n\n//define a reusable collision shape object\nlet triggerBox = new utils.TriggerBoxShape(Vector3.One(), Vector3.Zero())\n\n//create food\nconst food = new Entity()\nfood.addComponent(new ConeShape())\nfood.getComponent(ConeShape).withCollisions = false\nfood.addComponent(\n  new Transform({\n    position: new Vector3(1 + Math.random() * 14, 0, 1 + Math.random() * 14)\n  })\n)\nfood.addComponent(new utils.TriggerComponent(\n  triggerBox,\n    {\n\tlayer: foodLayer\n\ttriggeredByLayer: mouseLayer | catLayer\n\tonTriggerEnter: () => {\n\t  food.getComponent(Transform).position = new Vector3(\n\t    1 + Math.random() * 14,\n\t    0,\n\t    1 + Math.random() * 14\n\t  )\n\t  mouse.addComponentOrReplace(\n\t    new utils.MoveTransformComponent(\n\t\tmouse.getComponent(Transform).position,\n\t\tfood.getComponent(Transform).position,\n\t\t4\n\t    )\n\t  )\n\t  cat.addComponentOrReplace(\n\t    new utils.MoveTransformComponent(\n\t\tcat.getComponent(Transform).position,\n\t\tfood.getComponent(Transform).position,\n\t\t4\n\t    )\n\t )\n    }\n  })\n)\n\n//create mouse\nconst mouse = new Entity()\nmouse.addComponent(new SphereShape())\nmouse.getComponent(SphereShape).withCollisions = false\nmouse.addComponent(\n  new Transform({\n    position: new Vector3(1 + Math.random() * 14, 0, 1 + Math.random() * 14),\n    scale: new Vector3(0.5, 0.5, 0.5)\n  })\n)\nmouse.addComponent(new utils.TriggerComponent(\n  triggerBox,\n    {\n\tlayer: mouseLayer\n\ttriggeredByLayer: catLayer\n\tonTriggerEnter: () => {\n\t  mouse.getComponent(Transform).position = new Vector3(\n\t    1 + Math.random() * 14,\n\t    0,\n\t    1 + Math.random() * 14\n\t  )\n\t  mouse.addComponentOrReplace(\n\t    new utils.MoveTransformComponent(\n\t      mouse.getComponent(Transform).position,\n\t      food.getComponent(Transform).position,\n\t      4\n\t    )\n      )\n    }\n  })\n)\n\n//create cat\nconst cat = new Entity()\ncat.addComponent(new BoxShape())\ncat.getComponent(BoxShape).withCollisions = false\ncat.addComponent(\n  new Transform({\n    position: new Vector3(1 + Math.random() * 14, 0, 1 + Math.random() * 14)\n  })\n)\ncat.addComponent(new utils.TriggerComponen(\n\ttriggerBox,\n\t{\n\t\tlayer: catLayer\n\t})\n)\n\n//set initial movement for mouse and cat\nmouse.addComponentOrReplace(\n  new utils.MoveTransformComponent(\n    mouse.getComponent(Transform).position,\n    food.getComponent(Transform).position,\n    4\n  )\n)\ncat.addComponentOrReplace(\n  new utils.MoveTransformComponent(\n    cat.getComponent(Transform).position,\n    food.getComponent(Transform).position,\n    4\n  )\n)\n\n//add entities to engine\nengine.addEntity(food)\nengine.addEntity(mouse)\nengine.addEntity(cat)\n```\n\n## Conversions\n\nThis library includes a number of helpful functions for common value conversions.\n\n#### Clamp\n\nUse the `clamp()` function to easily clamp possible values between a maximum and a minimum.\n\nThe `clamp()` function takes the following arguments:\n\n- `value`: Input number to convert\n- `min`: Minimum output value.\n- `max`: Maximum output value.\n\nThe following example limits an incoming value between 5 and 15. If the incoming value is less than 5, it will output 5. If the incoming value is more than 15, it will output 15.\n\n```ts\nlet input = 200\nlet result = utils.clamp(input, 5, 15)\nlog(result)\n```\n\n#### Map\n\nUse the `map()` function to map a value from one range of values to its equivalent, scaled in proportion to another range of values, using maximum and minimum.\n\nThe `map()` function takes the following arguments:\n\n- `value`: Input number to convert\n- `min1`: Minimum value in the range of the input.\n- `max1`: Maximum value in the range of the input.\n- `min2`: Minimum value in the range of the output.\n- `max2`: Maximum value in the range of the output.\n\nThe following example maps the value _5_ from a scale of 0 to 10 to a scale of 300 to 400. The resulting value is 350, as it keeps the same proportion relative to the new maximum and minimum values.\n\n```ts\nlet input = 5\nlet result = utils.map(input, 0, 10, 300, 400)\nlog(result)\n```\n\n#### World position\n\nIf an entity is parented to another entity, or to the player, then its Transform position will be relative to its parent. To find what its global position is, taking into account any parents, use `getEntityWorldPosition()`.\n\nThe `getEntityWorldPosition()` function takes a single argument:\n\n- `entity`: The entity from which to get the global position\n\nThe function returns a `Vector3` object, with the resulting position of adding the given entity and all its chain of parents.\n\nThe following example sets a cube as a child of the player, and logs its true position when clicked.\n\n```ts\nconst cube = new Entity()\ncube.addComponent(new Transform({ position: new Vector3(0, 0, 1) }))cube.addComponent(new BoxShape())\nengine.addEntity(cube)\ncube.setParent(Attachable.FIRST_PERSON_CAMERA)\n\ncube.addComponent(\n  new OnPointerDown(() => {\n\tlog(getEntityWorldRotation(myCube))\n  }))\n```\n\n#### World rotation\n\nIf an entity is parented to another entity, or to the player, then its Transform rotation will be relative to its parent. To find what its global rotation is, taking into account any parents, use `getEntityWorldRotation()`.\n\nThe `getEntityWorldRotation()` function takes a single argument:\n\n- `entity`: The entity from which to get the global rotation\n\nThe function returns a `Quaternion` object, with the resulting rotation of multiplying the given entity to all its chain of parents.\n\nThe following example sets a cube as a child of the player, and logs its true rotation when clicked.\n\n```ts\nconst cube = new Entity()\ncube.addComponent(new Transform({ position: new Vector3(0, 0, 1) }))cube.addComponent(new BoxShape())\nengine.addEntity(cube)\ncube.setParent(Attachable.FIRST_PERSON_CAMERA)\n\ncube.addComponent(\n  new OnPointerDown(() => {\n\tlog(getEntityWorldRotation(myCube))\n  }))\n```\n\n## Send requests\n\nUse the `sendRequest()` function to easily send HTTP requests to APIs.\n\nThe `sendRequest()` function has a single required argument:\n\n- `url`: The URL to send the request\n\n```ts\nasync function request() {\n  let response = await utils.sendRequest(\n    'https://events.beland.io/api/events/?limit=5'\n  )\n\n  log(response)\n}\n```\n\n> NOTE: The sendRequest() function is asynchronous, since it must wait for the external server to respond back before it can return a response. If you need your code to access the data on the request's response, you must use the sendRequest() within an `async` block of code, and add an `await` to the function.\n\nThe `sendRequest()` function also lets you use the following arguments, for sending more advanced requests:\n\n- `method`: The HTTP method to use. `GET` is the default, other common options are `POST`, `PUT`, and `DELETE`.\n- `headers`: The HTTP headers of the request, as a JSON object.\n- `body`: The body of the request, as a JSON object.\n\n```ts\nasync function request() {\n    let response = await utils.sendRequest(\n        'https://jsonplaceholder.typicode.com/posts',\n        'POST',\n        {\n            'content-type': 'application/json',\n        },\n        {\n            content: 'My test JSON',\n        }\n    )\n}\n```\n\n## Labels\n\nAdd a text label floating over an entity using `addLabel()`.\n\nThe `addLabel()` function has just two required arguments:\n\n- `text`: The string of text to display\n- `parent`: The entity to set the label on\n\n```ts\nconst cube = new Entity()\ncube.addComponent(new Transform({ position: new Vector3(8, 1, 8) }))\ncube.addComponent(new BoxShape())\nengine.addEntity(cube)\n\nutils.addLabel('Random Cube', cube)\n```\n\nThe `addLabel()` function also lets you set the following:\n\n- `billboard`: If true, label turns to always face player. True by default.\n- `color`: Text color. Black by default.\n- `size`: Text font size, 3 by default.\n- `textOffset`: Offset from parent entity's position. By default 1.5 meters above the parent.\n\n> Tip: The `addLabel()` function returns the created entity used for the text. You can then tweak this entity in any way you choose.\n\n## Debug helpers\n\n#### Debug cube\n\nRender a simple clickable cube to use as a trigger when debugging a scene with `addTestCube()`.\n\n> NOTE: The test cube is only shown in preview, unless configured to appear also in production.\n\nThe `addTestCube()` function has just two required arguments:\n\n- `pos`: The position, rotation and/or scale of the cube, expressed as a TransformConstructorArgs object, as gets passed when creating a `Transform` component.\n- `triggeredFunction`: A function that gets called every time the cube is clicked.\n\n```ts\nutils.addTestCube({ position: new Vector3(2, 1, 2) }, () => {\n  log('Cube clicked')\n})\n```\n\nThe `addTestCube()` function also lets you set the following:\n\n- `label`: An optional label to display floating over the cube\n- `color`: A color for the cube's material.\n- `sphere`: If true, it renders as a Sphere instead of a cube.\n- `noCollider`: If true, the cube won't have a collider and will let players walk through it.\n- `keepInProduction`: If true, it will be visible for players in-world once the scene is deployed. Otherwise, the cube is only present when previewing he scene locally.\n\n> Tip: The `addTestCube()` function returns the created entity for the cube. You can then tweak this entity in any way you choose. `addTestCube()` is an async function (because the function first checks if you're in preview or in production). If you need the function to return the cube (instead of a promise of a cube) use it inside an async block of code with an await on the `addTestCube()` function.\n\n```ts\nasync function addMyCube() {\n  myCube = await utils.addTestCube({ position: new Vector3(0, 0, 1) }, () => {\n    log('Cube clicked')\n  })\n}\n```\n\n## Action sequence\n\nUse an action sequence to play a series of actions one after another.\n\n### IAction\n\nThe `IAction` interface defines the actions that can be added into a sequence. It includes:\n\n- `hasFinished`: Boolean for the state of the action, wether it has finished its execution or not.\n- `onStart()`: First method that is called upon the execution of the action.\n- `update()`: Called on every frame on the action's internal update.\n- `onFinish()`: Called when the action has finished executing.\n\n### Action Sequence Builder\n\nThis object creates action sequences, using simple building blocks.\n\nThe `SequenceBuilder` exposes the following methods:\n\n- `then()`: Enqueue an action so that it's executed when the previous one finishes.\n- `if()`: Use a condition to branch the sequence\n- `else()`: Used with if() to create an alternative branch\n- `endIf()`: Ends the definition of the conditional block\n- `while()`: Keep running the actions defined in a block until a condition is no longer met.\n- `breakWhile()`: Ends the definition of the while block\n\n### Action Sequence System\n\nThe action sequence system takes care of running the sequence of actions. The `ActionsSequenceSystem` exposes the following methods:\n\n- `startSequence()`: Starts a sequence of actions\n- `setOnFinishCallback()`: Sets a callback for when the whole sequence is finished\n- `isRunning()`: Returns a boolean that determines if the sequence is running\n- `stop()`: Stops a running the sequence\n- `resume()`: Resumes a stopped sequence\n- `reset()`: Resets a sequence so that it starts over\n\n### Full example\n\nThe following example creates a box that changes its scale until clicked. Then it resets its scale and moves.\n\n```ts\nimport * as utils from '@beland/ecs-scene-utils'\n\n//set clicked flag\nlet boxClicked = false\n\n//create box entity\nconst box = new Entity()\nbox.addComponent(new BoxShape())\nbox.addComponent(new Transform({ position: new Vector3(14, 0, 14) }))\nbox.addComponent(new OnClick(() => (boxClicked = true)))\nengine.addEntity(box)\n\n//Use IAction to define action for scaling\nclass ScaleAction implements utils.ActionsSequenceSystem.IAction {\n  hasFinished: boolean = false\n  entity: Entity\n  scale: Vector3\n\n  constructor(entity: Entity, scale: Vector3) {\n    this.entity = entity\n    this.scale = scale\n  }\n\n  //Method when action starts\n  onStart(): void {\n    const transform = this.entity.getComponent(Transform)\n    this.hasFinished = false\n\n    this.entity.addComponentOrReplace(\n      new utils.ScaleTransformComponent(\n        transform.scale,\n        this.scale,\n        1.5,\n        () => {\n          this.hasFinished = true\n        },\n        utils.InterpolationType.EASEINQUAD\n      )\n    )\n  }\n  //Method to run on every frame\n  update(dt: number): void {}\n  //Method to run at the end\n  onFinish(): void {}\n}\n\n//Use IAction to define action for movement\nclass MoveAction implements utils.ActionsSequenceSystem.IAction {\n  hasFinished: boolean = false\n  entity: Entity\n  position: Vector3\n\n  constructor(entity: Entity, position: Vector3) {\n    this.entity = entity\n    this.position = position\n  }\n\n  //Method when action starts\n  onStart(): void {\n    const transform = this.entity.getComponent(Transform)\n\n    this.entity.addComponentOrReplace(\n      new utils.MoveTransformComponent(\n        transform.position,\n        this.position,\n        4,\n        () => {\n          this.hasFinished = true\n        }\n      )\n    )\n  }\n  //Method to run on every frame\n  update(dt: number): void {}\n  //Method to run at the end\n  onFinish(): void {}\n}\n\n//Use sequence builder to create a sequence\nconst sequence = new utils.ActionsSequenceSystem.SequenceBuilder()\n  .while(() => !boxClicked)\n  .then(new ScaleAction(box, new Vector3(1.5, 1.5, 1.5)))\n  .then(new ScaleAction(box, new Vector3(0.5, 0.5, 0.5)))\n  .endWhile()\n  .then(new ScaleAction(box, new Vector3(1, 1, 1)))\n  .then(new MoveAction(box, new Vector3(1, 0, 1)))\n\n//Create a sequence system, and add it to the engine to run the sequence\nengine.addSystem(new utils.ActionsSequenceSystem(sequence))\n```\n\n\n## Contribute\n\nAll contributions from the community are encouraged as Pull Requests to this repository. Please notify of any PRs in the Beland Discord channels to make sure the team is aware of them.\n\nIn order to test any changes made to this library on active scenes, follow these steps:\n\n1. Run `npm run build` to build internal dependencies in the project folder\n2. Run `npm run link` on this repository\n3. Create a new BLD scene, or pick an existing one\n4. Install the library normally with `npm i @beland/ecs-scene-utils -B`\n5. Import the library normally into the project with `import * as utils from '@beland/ecs-scene-utils'` \n6. On the scene folder, run `npm link @beland/ecs-scene-utils`\n7. Use this scene to try out any functionality you've added or changed to verify that it behaves as expected.\n\n> Note: When done testing, run `npm unlink @beland/ecs-scene-utils` on your scene, so that it no longer depends on your local copy of the library.\n","readmeFilename":"README.md"}