` currently only accepts 1 string flag from the user. Using only flags means the system relies solely on us predicting users' needs and implementing a \"mode\" for them.\r\nAccepting only a single flag means we can't have a compound policy, e.g., \"rerender if advance or invalidate were called or the window resized. Afaik, this currently leads to cases where manual is the mode – the canvas will be blank if the window is resized, until invalidate is called.\r\n\r\n\r\n\r\n### Suggested solution\r\n\r\nEncapsulate the logic for \"Should the next tick update/render?\" in a module – maybe `src/core/renderPolicy.ts`?\r\nLet the render policy be specified via functions/objects as follows:\r\n\r\n```ts\r\nimport { createRenderPolicy, manual } from '...'\r\nconst policy = createRenderPolicy(manual)\r\nconst { invalidate } = policy\r\n...\r\n\u003CTresCanvas :render-policy=\"policy\" />\r\n```\r\n\r\nAbove, \r\n\r\n- manual is \"rule\" function that contains its own state, tracking if invalidate() was called since the last update.\r\n- policy is an object that relays calls to invalidate and advance to its rules, then asks the rules if the next tick should update/render or not.\r\n\r\nIn this way, we could have compound policies. E.g.,\r\n\r\n```ts\r\n// NOTE: This policy will approve the next tick of jobs if ...\r\n// - `invalidate()` was called\r\n// - the window was resized\r\n// but cancel if ...\r\n// - the canvas is off-screen\r\nconst { shouldUpdate, invalidate } = createRenderPolicy([manual, windowResize, cancelIfOffScreen])\r\nshouldUpdate() // false\r\ninvalidate()\r\nshouldUpdate() // true\r\n```\r\n\r\nRules would be evaluated in FILO order, with the result of lower ranking rules being passed to higher ranking rules, so this ...\r\n\r\n```\r\ncreateRenderPolicy([manual, cancelIfOffScreen, windowResize])\r\n```\r\n\r\n... cancels true from windowResize if the canvas is offscreen. But if the canvas is off-screen, manual's advance(n) will still take precedence.\r\n\r\nWhereas here ...\r\n\r\n```\r\ncreateRenderPolicy([cancelIfOffScreen, manual, windowResize])\r\n```\r\n\r\n... `cancelIfOffScreen` takes precedence over the other 2 rules and cancels both if the canvas is off-screen. \r\n----\r\n\r\nRules are relatively simple to write and users could supply their own rules, if we surface that in the API. Here's a \"complicated\" rule – `windowResize` – in its current form:\r\n\r\n```ts\r\nexport const windowResize: CreateUpdateRule = () => {\r\n let invalidated = true\r\n const invalidate = () => { invalidated = true }\r\n window.addEventListener('resize', invalidate)\r\n return {\r\n shouldUpdate: (lowRankResult: boolean) => {\r\n const result = invalidated\r\n invalidated = false\r\n return result || lowRankResult\r\n },\r\n dispose: () => {\r\n window.removeEventListener('resize', invalidate)\r\n }\r\n }\r\n}\r\n```\r\nHere's manual:\r\n\r\n```ts\r\nexport const manual: CreateUpdateRule = () => {\r\n let numFramesToAdvance = 0\r\n return {\r\n advance: (numFrames = 1) => {\r\n numFramesToAdvance = Math.max(numFramesToAdvance, numFrames)\r\n },\r\n shouldUpdate: (lowRankResult: boolean) => {\r\n const result = numFramesToAdvance > 0\r\n numFramesToAdvance = Math.max(0, numFramesToAdvance - 1)\r\n return result || lowRankResult\r\n }\r\n }\r\n}\r\n```\r\n\r\n### Alternative\r\n\r\n_No response_\r\n\r\n### Additional context\r\n\r\n_No response_\r\n\r\n### Validations\r\n\r\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\r\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\r\n- [X] Read the [docs](https://tresjs.org/guide).\r\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.\r\n\r\nEdit (andretchen0): fixed formatting ",[2884,2887],{"name":2885,"color":2886},"feature","c2e0c6",{"name":2888,"color":2889},"pending-triage","97A4FE",689,"Render mode policies","2024-05-24T14:21:03Z","https://github.com/Tresjs/tres/issues/689",0.7361665,{"description":2896,"labels":2897,"number":2898,"owner":2874,"repository":2875,"state":2876,"title":2899,"updated_at":2900,"url":2901,"score":2902},"### Description\n\nFirst of all, thank you for your work! Tresjs has really helped us keeping a composable and declarative structure for our 3D scenes, with a seamless integration with Vue.\r\n\r\nAs our app grew, we have noticed that the rendering loop is using a significant part of the resources on low-end platforms. This was honestly not much of an issue before we started using web workers to offload some computationally intensive tasks. We noticed that the browser is highly prioritizing the main thread over the web workers, making them virtually useless when the main loop is too demanding.\n\n### Suggested solution\n\nWe would like to have the rendering loop and all the Tree artillery in a dedicated web worker with the help of an [offscreen canvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas).\r\n\r\nNote that this would imply some _asynchronous_ messaging system between the DOM thread and the worker using [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage).\n\n### Alternative\n\nLimiting the FPS is a workaround, but it does not really solve the problem because it won't adapt to the available computational power. \n\n### Additional context\n\n_No response_\n\n### Validations\n\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\n- [X] Read the [docs](https://tresjs.org/guide).\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.",[],833,"Rendering loop in web worker","2024-09-16T08:24:26Z","https://github.com/Tresjs/tres/issues/833",0.7418658,{"description":2904,"labels":2905,"number":2909,"owner":2874,"repository":2910,"state":2876,"title":2911,"updated_at":2912,"url":2913,"score":2914},"The current API is far from ideal, we initially followed the same DX as https://github.com/pmndrs/leva \r\nbut encountered number of issues\"\r\n\r\n- Need to use `value.value` for multiple controls #92 \r\n- Shared `useControls` composable, impossible to have multiple distinct instances #98 \r\n\r\nI will copy the different suggestions from @andretchen0 \r\n\r\n## Example: Tweakpane\r\n\r\n[Tweakpane | Bindings](https://tweakpane.github.io/docs/input-bindings/)\r\n\r\nTweakpane uses `.addBinding(stateObject, key, params)`.\r\n\r\n```ts\r\nconst PARAMS = {\r\n speed: 50,\r\n};\r\n\r\nconst pane = new Pane();\r\npane.addBinding(PARAMS, 'speed', {\r\n min: 0,\r\n max: 100,\r\n});\r\n```\r\n\r\nWith this setup, there's no need for a `watch` and so no `value.value`. The value is already being \"watched\" with the configuration above.\r\n\r\n## Example: v-tweakpane\r\n\r\nA variation of Tweakpane, this time with Vue. Like Tweakpane, it uses a specific method for creating a widget and binding at the same time. This avoids the need to `watch` and avoids `.value.value`.\r\n\r\n```ts\r\nconst onPaneTwoCreated = (pane: any) => {\r\n pane.registerPlugin(CamerakitPlugin);\r\n const PARAMS = {\r\n flen: 55,\r\n fnum: 1.8,\r\n iso: 100,\r\n };\r\n pane.addInput(PARAMS, 'flen', {\r\n view: 'cameraring',\r\n series: 0,\r\n unit: { pixels: 50, ticks: 10, value: 0.2 },\r\n min: 1,\r\n step: 0.02,\r\n });\r\n```\r\n\r\nThe [example](https://github.com/vinayakkulkarni/v-tweakpane/blob/main/example/src/App.vue) uses some callbacks for setup, which Leches doesn't need. Personally, I'd like to avoid having those.\r\n\r\n## Example: Vuetify\r\n\r\nIn this [Vuetify example](https://vuetifyjs.com/en/components/sliders/#min-and-max), most of the config that Leches does in `\u003Csetup>` is handled in `\u003Ctemplate>`. Bindings are created using `v-model` in the `\u003Ctemplate>`.\r\n\r\n```html\r\n\u003Ctemplate>\r\n \u003Cv-slider\r\n v-model=\"slider\"\r\n class=\"align-center\"\r\n :max=\"max\"\r\n :min=\"min\"\r\n hide-details\r\n >\r\n \u003Ctemplate v-slot:append>\r\n \u003Cv-text-field\r\n v-model=\"slider\"\r\n hide-details\r\n single-line\r\n density=\"compact\"\r\n type=\"number\"\r\n style=\"width: 70px\"\r\n >\u003C/v-text-field>\r\n \u003C/template>\r\n \u003C/v-slider>\r\n\u003C/template>\r\n\r\n\u003Cscript>\r\n export default {\r\n data () {\r\n return {\r\n min: -50,\r\n max: 90,\r\n slider: 40,\r\n }\r\n },\r\n }\r\n\u003C/script>\r\n```",[2906],{"name":2907,"color":2908},"enhancement","a2eeef",104,"leches","Rethink API and DX","2024-04-27T19:31:44Z","https://github.com/Tresjs/leches/issues/104",0.76551116,{"description":2916,"labels":2917,"number":2927,"owner":2874,"repository":2875,"state":2876,"title":2928,"updated_at":2929,"url":2930,"score":2931},"### Describe the bug\r\n\r\n`useTresContext().controls.value` is null when using Cientos' `\u003COrbitControls>`.\r\n\r\n### Context\r\n\r\n[This issue was opened on Cientos.](https://github.com/Tresjs/cientos/issues/249) Part of the issue was addressed with a Cientos' PR. \r\n\r\nOpening an issue here to look into `useTresContext().controls`. \r\n\r\n----\r\n\r\n@zkobrinsky\r\n\r\n### Reproduction\r\n\r\nhttps://stackblitz.com/edit/tresjs-basic-fzdwdc?file=src%2Fcomponents%2FTheScene.vue\r\n\r\n### Steps to reproduce\r\n\r\n_No response_\r\n\r\n### System Info\r\n\r\n_No response_\r\n\r\n### Used Package Manager\r\n\r\nnpm\r\n\r\n### Code of Conduct\r\n\r\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\r\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\r\n- [X] Read the [docs](https://tresjs.org/guide).\r\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.\r\n- [X] The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.",[2918,2921,2924],{"name":2919,"color":2920},"bug","d73a4a",{"name":2922,"color":2923},"waiting for author","B145BC",{"name":2925,"color":2926},"v4","7980EA",418,"useTresContext().controls.value is null when using Cientos' `\u003COrbitControls />`","2024-08-21T10:29:21Z","https://github.com/Tresjs/tres/issues/418",0.768294,{"description":2933,"labels":2934,"number":2940,"owner":2874,"repository":2875,"state":2941,"title":2942,"updated_at":2943,"url":2944,"score":2945},"### Description\r\n\r\n## Problem\r\n\r\nUpdates/renders share the same unordered-from-the-components-perspective callback \"slot\", leading to out-of-sync visuals.\r\n\r\n## Example\r\n\r\nHere's the Cientos' playground demo for `MeshReflectionMaterial`. Notice the extra \"jumps\" in the reflection:\r\n\r\nhttps://github.com/Tresjs/tres/assets/20469369/314a4154-7cef-47d0-977e-e98fd53c8c13\r\n\r\nHere are two adjacent frames. Notice that the \"real\" elements haven't moved, but the reflection \"jumps\" from one frame to the next:\r\n\r\n\u003Cimg width=\"1044\" alt=\"Screenshot 2024-03-29 at 15 13 35\" src=\"https://github.com/Tresjs/tres/assets/20469369/47a6f2d1-817c-4bf1-a164-70969fb3aa7d\">\r\n\r\n## Why it happens\r\n\r\nThe \"jumps\" occur because the updates/renders are all firing in `onLoop`, but out-of-order from the perspective of the FBO reflection. So for a file like this ...\r\n\r\n```vue\r\n\u003Cscript setup lang=\"ts\">\r\nimport { TresCanvas, useRenderLoop } from '@tresjs/core'\r\nimport DemoComponent from './DemoComponent.vue'\r\n\r\nconst { onLoop } = useRenderLoop()\r\n\r\nonLoop(({ elapsed }) => {\r\n console.log(\"Demo update\", elapsed)\r\n})\r\n\u003C/script>\r\n\r\n\u003Ctemplate>\r\n \u003CTresCanvas>\r\n \u003CTresPerspectiveCamera />\r\n \u003CDemoComponent>\u003C/DemoComponent>\r\n \u003C/TresCanvas>\r\n\u003C/template>\r\n\r\n```\r\n\r\n... a single \"tick\" of `onLoop` looks like this:\r\n\r\n\u003Cimg width=\"238\" alt=\"Screenshot 2024-03-29 at 16 41 44\" src=\"https://github.com/Tresjs/tres/assets/20469369/63d33e65-de88-48dc-859d-709863672227\">\r\n\r\nWith this ordering, if `DemoComponent` renders the scene to an FBO, and is then rendered to the screen, it'll always be 1 frame behind `Demo`.\r\n\r\n\r\n\r\n### Suggested solution\r\n\r\nWe could follow R3F's lead here:\r\n\r\n* [Guarantee that rendering happens after `onLoop`](https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe)\r\n* Implement these:\r\n** https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop\r\n** https://docs.pmnd.rs/react-three-fiber/api/hooks#negative-indices\r\n\r\nFor example, R3F's `OrbitControls` uses a negative index:\r\n\r\nhttps://github.com/pmndrs/drei/blob/c147c2b1064bc4b457150f995bf714c2e43cf56f/src/core/OrbitControls.tsx#L58C1-L61C13\r\n\r\nIf I understand correctly, that means that the OrbitControls camera is updated before the rest of the scene, which is important in the case of FBOs like in the reflection material.\r\n\r\n### Alternative\r\n\r\nAs a simpler – though less flexible – solution, we could add a few callbacks:\r\n\r\n* `useRenderLoop().onBeforeRender()` – for FBOs\r\n* `useRenderLoop().onRender()` – for actually rendering to the screen\r\n\r\n### Additional context\r\n\r\n_No response_\r\n\r\n### Validations\r\n\r\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\r\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\r\n- [X] Read the [docs](https://tresjs.org/guide).\r\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.",[2935,2936,2937],{"name":2919,"color":2920},{"name":2885,"color":2886},{"name":2938,"color":2939},"p2-to-be-discussed","97C1B1",607,"closed","`useRenderLoop`: render after updates","2024-05-30T06:58:57Z","https://github.com/Tresjs/tres/issues/607",0.6517291,{"description":2947,"labels":2948,"number":2955,"owner":2874,"repository":2875,"state":2941,"title":2956,"updated_at":2957,"url":2958,"score":2959},"### Description\r\n\r\n`useRenderLoop` is used to provide the end user a callback method `onLoop` every frame per second to align with the one that the core uses for rendering.\r\n\r\nIt's based on `useRafn` composable from `@vueuse/core` https://vueuse.org/core/useRafFn/ but due to the feedback of the community, there are few issues related to its current behavior:\r\n\r\n- #607 \r\n- #252 \r\n- tresjs/nuxt#97\r\n\r\n### Suggested solution\r\n\r\nRefactor `useRenderLoop` to move away from `useRafn`\r\n\r\n### Alternative\r\n\r\n_No response_\r\n\r\n### Additional context\r\n\r\n_No response_\r\n\r\n### Validations\r\n\r\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\r\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\r\n- [X] Read the [docs](https://tresjs.org/guide).\r\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.",[2949,2952],{"name":2950,"color":2951},"experimental","01D7E6",{"name":2953,"color":2954},"breaking-change","5612D2",633,"Reconsider how useRenderLoop works.","2024-05-30T06:43:03Z","https://github.com/Tresjs/tres/issues/633",0.67421883,{"description":2961,"labels":2962,"number":2965,"owner":2874,"repository":2875,"state":2941,"title":2966,"updated_at":2967,"url":2968,"score":2969},"**Describe the bug**\r\nWhen using any of the loops from renderLoops composable, `delta = clock.getDelta()` is always 0, it can't be used for animation\r\n\r\n\r\n**Reproduction**\r\n[Reproduction Link\r\n](https://stackblitz.com/edit/tresjs-basic-animations?file=src%2Fcomponents%2FTheExperience.vue)\r\n\r\n**Steps**\r\nSteps to reproduce the behavior:\r\n1. Go to 'TheExperience.vue`\r\n2. Check the `onLoop`composable callback\r\n3. Console delta\r\n4. See value\r\n\r\n**Expected behavior**\r\nDelta should be the seconds passed since the time [.oldTime](https://threejs.org/docs/index.html#api/en/core/Clock.oldTime) was set and sets [.oldTime](https://threejs.org/docs/index.html#api/en/core/Clock.oldTime) to the current time.\r\nIf [.autoStart](https://threejs.org/docs/index.html#api/en/core/Clock.autoStart) is true and the clock is not running, also starts the clock\r\n\r\n**Screenshots**\r\nIf applicable, add screenshots to help explain your problem.\r\n\r\n**System Info**\r\nOutput of `npx envinfo --system --npmPackages '{vite,@tresjs/*, three, vue}' --binaries --browsers` \r\n\r\n```\r\n System:\r\n OS: Linux 5.0 undefined\r\n CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz\r\n Memory: 0 Bytes / 0 Bytes\r\n Shell: 1.0 - /bin/jsh\r\n Binaries:\r\n Node: 16.14.2 - /usr/local/bin/node\r\n Yarn: 1.22.19 - /usr/local/bin/yarn\r\n npm: 7.17.0 - /usr/local/bin/npm\r\n npmPackages:\r\n @tresjs/cientos: ^1.0.0 => 1.0.0 \r\n @tresjs/core: ^1.1.0 => 1.1.0 \r\n vite: ^3.2.4 => 3.2.4 \r\n```\r\n",[2963,2964],{"name":2919,"color":2920},{"name":2868,"color":2869},81,"onLoop delta is always 0","2023-01-17T09:16:52Z","https://github.com/Tresjs/tres/issues/81",0.7050046,{"description":2971,"labels":2972,"number":2974,"owner":2874,"repository":2875,"state":2941,"title":2975,"updated_at":2976,"url":2977,"score":2978},"### Describe the bug\n\nThe official [Vue devtools](https://github.com/vuejs/devtools) is broken since v2. Most probably related to the edge case of the use of a custom renderer.\r\n\r\n\n\n### Reproduction\n\nhttps://stackblitz.com/edit/stackblitz-starters-sa3ruk?file=README.md\n\n### Steps to reproduce\n\nOpen in a new tab\r\nCheck dev tools\r\nCheck error in console\r\n\r\n```\r\nTypeError: Cannot read properties of undefined (reading 'ownerDocument')\r\n```\n\n### System Info\n\n_No response_\n\n### Used Package Manager\n\npnpm\n\n### Code of Conduct\n\n- [X] I agree to follow this project's [Code of Conduct](https://github.com/Tresjs/tres/blob/main/CODE_OF_CONDUCT.md)\n- [X] Read the [Contributing Guidelines](https://github.com/Tresjs/tres/blob/main/CONTRIBUTING.md).\n- [X] Read the [docs](https://tresjs.org/guide).\n- [X] Check that there isn't [already an issue](https://github.com/tresjs/tres/issues) that reports the same bug to avoid creating a duplicate.\n- [X] The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.",[2973],{"name":2919,"color":2920},317,"Vue-devtools broken since v2 custom renderer","2023-08-23T05:12:31Z","https://github.com/Tresjs/tres/issues/317",0.7492984,{"description":2980,"labels":2981,"number":1665,"owner":2874,"repository":2986,"state":2941,"title":2987,"updated_at":2988,"url":2989,"score":2990},"**Describe the bug**\r\nGLTF Model is trying to return the model by ref before the variable is initialized on model load\r\n\r\n\r\n**Reproduction**\r\n[Reproduction](https://stackblitz.com/edit/tresjs-gltfmodel-2stucs?file=package.json,src%2Fcomponents%2FTheExperience.vue,src%2Fstyle.css)\r\n\r\n**Expected behavior**\r\nError on console disappears and model is returned successfully via templateref\r\n\r\n**System Info**\r\nOutput of `npx envinfo --system --npmPackages '{vite,@tresjs/*, three, vue}' --binaries --browsers` \r\n\r\n```\r\n System:\r\n OS: Linux 5.0 undefined\r\n CPU: (5) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz\r\n Memory: 0 Bytes / 0 Bytes\r\n Shell: 1.0 - /bin/jsh\r\n Binaries:\r\n Node: 16.14.2 - /usr/local/bin/node\r\n Yarn: 1.22.19 - /usr/local/bin/yarn\r\n npm: 7.17.0 - /usr/local/bin/npm\r\n npmPackages:\r\n @tresjs/cientos: ^2.0.0-alpha.0 => 2.0.0-alpha.1 \r\n @tresjs/core: ^2.0.0-alpha.0 => 2.0.0-alpha.1 \r\n vite: ^3.2.4 => 3.2.5 \r\n```\r\n\r\n",[2982,2983],{"name":2919,"color":2920},{"name":2984,"color":2985},"v2","FEE22D","cientos","[v2] - GLTFModel: Cannot access 'a' before initialization","2023-03-23T08:17:47Z","https://github.com/Tresjs/cientos/issues/11",0.74991995,["Reactive",2992],{},["Set"],["ShallowReactive",2995],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fIblDDXdr7FnjvlGbvZzuN6p4gHHgwohelgTJtDJ0-9M":-1},"/Tresjs/tres/595"]