` 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 ",[3035,3036],{"name":3019,"color":3020},{"name":3037,"color":3038},"pending-triage","97A4FE",689,"Render mode policies","2024-05-24T14:21:03Z","https://github.com/Tresjs/tres/issues/689",0.7718546,{"description":3045,"labels":3046,"number":3050,"owner":3025,"repository":3051,"state":3027,"title":3052,"updated_at":3053,"url":3054,"score":3055},"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```",[3047],{"name":3048,"color":3049},"enhancement","a2eeef",104,"leches","Rethink API and DX","2024-04-27T19:31:44Z","https://github.com/Tresjs/leches/issues/104",0.77279985,{"description":3057,"labels":3058,"number":3059,"owner":3025,"repository":3026,"state":3027,"title":3060,"updated_at":3061,"url":3062,"score":3063},"### 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.7728599,{"description":3065,"labels":3066,"number":3068,"owner":3025,"repository":3069,"state":3027,"title":3070,"updated_at":3071,"url":3072,"score":3073},"### Description\n\nAs a maintainer of TresJ, I want to keep the core's as minimal and predictable as possible and move DX-enhanced abstractions like `useTexture` to cientos.\n\n### Suggested solution\n\nMove `useTexture` composable to this repo. Based on https://github.com/Tresjs/tres/issues/922 and https://github.com/Tresjs/tres/pull/949\n\n### Alternative\n\n_No response_\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/cientos/blob/main/CODE_OF_CONDUCT.md)\n- [x] Read the [Contributing Guidelines](https://github.com/Tresjs/cientos/blob/main/CONTRIBUTING.md).\n- [x] Read the [docs](https://cientos.tresjs.org/guide).\n- [x] Check that there isn't [already an issue](https://github.com/tresjs/cientos/issues) that reports the same bug to avoid creating a duplicate.",[3067],{"name":3019,"color":3020},611,"cientos","Move core's useTexture to cientos","2025-04-12T06:34:16Z","https://github.com/Tresjs/cientos/issues/611",0.786715,{"description":3075,"labels":3076,"number":3080,"owner":3025,"repository":3026,"state":3081,"title":3082,"updated_at":3083,"url":3084,"score":3085},"**Is your feature request related to a problem? Please describe.**\r\nIn the current implementation, `useTres` uses a [global state](https://github.com/Tresjs/tres/blob/196606faba790a81dc9b8cdf36133400bcdbb545/src/composables/useTres/index.ts#L100) which has some downsides.\r\n\r\n1. It prevents having multiple canvases on the same page. Fixing this issue might help solving #153 \r\n2. Fixing this issue might help solving #173 \r\n3. Global states are prone to [cross-request state pollution](https://vuejs.org/guide/scaling-up/ssr.html#cross-request-state-pollution) in the SSR context\r\n4. One could put anything inside the state by using [setState](https://github.com/Tresjs/tres/blob/196606faba790a81dc9b8cdf36133400bcdbb545/src/composables/useTres/index.ts#L128), but there would be no representation of it in [TresState](https://github.com/Tresjs/tres/blob/196606faba790a81dc9b8cdf36133400bcdbb545/src/composables/useTres/index.ts#L5). DX suffers from this.\r\n\r\n**Describe the solution you'd like**\r\nWe could restructure `useTres` to make it use the [provide context pattern](https://medium.com/@maoberlehner/context-and-provider-pattern-with-the-vue-3-composition-api-17247eb7b001). `TresCanvas` would be the entity to provide things like renderer, camera and so on (see [TresState](https://github.com/Tresjs/tres/issues/new?assignees=&labels=enhancement&template=feature-request-%F0%9F%AA%90.md)). Any entity being child of `TresCanvas` could use the composable that injects those things.\r\n\r\n**Additional context**\r\nI'm not 100% sure if my proposed solution works. Let's see this issue as a opportunity for a little experiment 😊.\r\n",[3077],{"name":3078,"color":3079},"v2","FEE22E",183,"closed","feat: restructuring useTres using the provide context pattern","2023-04-04T15:47:17Z","https://github.com/Tresjs/tres/issues/183",0.6967966,{"description":3087,"labels":3088,"number":3090,"owner":3025,"repository":3091,"state":3081,"title":3092,"updated_at":3093,"url":3094,"score":3095},"**Is your feature request related to a problem? Please describe.**\r\nThe package should adapt to the changes made in https://github.com/Tresjs/tres/issues/331\r\n\r\n**Describe the solution you'd like**\r\nWe should refactor `useCore` and any use of the state.\r\n",[3089],{"name":3048,"color":3049},43,"post-processing","Refactor useCore to new state context provider","2023-08-18T10:20:59Z","https://github.com/Tresjs/post-processing/issues/43",0.73724335,{"description":3097,"labels":3098,"number":3102,"owner":3025,"repository":3026,"state":3081,"title":3103,"updated_at":3104,"url":3105,"score":3106},"### Description\r\n\r\nAs the author and maintainer of TresJS, I would like to simplify and clean the custom renderer `nodeOps` to make the code more readable and easier to maintain.\r\n\r\nAt, we are using overpopulation the property [userData](https://threejs.org/docs/#api/en/core/Object3D.userData) for the scene and objects on the scene graph as a workaround for accessing state or adding extra properties and methods that we need for TresJS nodeOps like this:\r\n\r\n` scene.userData.tres__registerAtPointerEventHandler = registerObject`\r\n\r\n`userData` is a property that the end-user can also use, we need to add the `.tres__` prefix to avoid naming collisions, adding an extra cognitive load to the code.\r\n\r\nCode ends up being kind of difficult to read:\r\n\r\n```ts\r\nremove(node) {\r\n if (!node) return\r\n // remove is only called on the node being removed and not on child nodes.\r\n\r\n if (node.isObject3D) {\r\n const object3D = node as unknown as Object3D\r\n\r\n const disposeMaterialsAndGeometries = (object3D: Object3D) => {\r\n const tresObject3D = object3D as TresObject3D\r\n\r\n if (!object3D.userData.tres__materialViaProp) {\r\n tresObject3D.material?.dispose()\r\n tresObject3D.material = undefined\r\n }\r\n\r\n if (!object3D.userData.tres__geometryViaProp) {\r\n tresObject3D.geometry?.dispose()\r\n tresObject3D.geometry = undefined\r\n }\r\n }\r\n\r\n const deregisterAtPointerEventHandler = scene?.userData.tres__deregisterAtPointerEventHandler\r\n const deregisterBlockingObjectAtPointerEventHandler\r\n = scene?.userData.tres__deregisterBlockingObjectAtPointerEventHandler\r\n\r\n const deregisterAtPointerEventHandlerIfRequired = (object: TresObject) => {\r\n\r\n if (!deregisterBlockingObjectAtPointerEventHandler)\r\n throw 'could not find tres__deregisterBlockingObjectAtPointerEventHandler on scene\\'s userData'\r\n\r\n scene?.userData.tres__deregisterBlockingObjectAtPointerEventHandler?.(object as Object3D)\r\n\r\n if (!deregisterAtPointerEventHandler)\r\n throw 'could not find tres__deregisterAtPointerEventHandler on scene\\'s userData'\r\n\r\n if (\r\n object && supportedPointerEvents.some(eventName => object[eventName])\r\n )\r\n deregisterAtPointerEventHandler?.(object as Object3D)\r\n }\r\n\r\n const deregisterCameraIfRequired = (object: Object3D) => {\r\n const deregisterCamera = scene?.userData.tres__deregisterCamera\r\n\r\n if (!deregisterCamera)\r\n throw 'could not find tres__deregisterCamera on scene\\'s userData'\r\n\r\n if ((object as Camera).isCamera)\r\n deregisterCamera?.(object as Camera)\r\n }\r\n\r\n node.removeFromParent?.()\r\n object3D.traverse((child: Object3D) => {\r\n disposeMaterialsAndGeometries(child)\r\n deregisterCameraIfRequired(child)\r\n deregisterAtPointerEventHandlerIfRequired?.(child as TresObject)\r\n })\r\n\r\n disposeMaterialsAndGeometries(object3D)\r\n deregisterCameraIfRequired(object3D)\r\n deregisterAtPointerEventHandlerIfRequired?.(object3D as TresObject)\r\n }\r\n\r\n node.dispose?.()\r\n },\r\n ``` \r\n\r\n### Suggested solution\r\n\r\nAdd a local state for each instance called `__tres` which contains:\r\n\r\n```ts\r\nexport interface LocalState = {\r\n type: string\r\n // objects and parent are used when children are added with `attach` instead of being added to the Object3D scene graph\r\n objects: Instance[]\r\n parent: Instance | null\r\n primitive?: boolean\r\n eventCount: number\r\n handlers: Partial\u003CEventHandlers>\r\n memoizedProps: { [key: string]: any }\r\n}\r\n```\r\n\r\n```ts\r\nexport interface TresObject3D extends THREE.Object3D\u003CTHREE.Object3DEventMap> {\r\n geometry?: THREE.BufferGeometry & TresBaseObject\r\n material?: THREE.Material & TresBaseObject\r\n __tres: LocalState\r\n}\r\n```\r\n\r\nWe could include the context of TresContextProvider on the scene object to handle the register of cameras and event handlers or even inside each LocalState on a potential property `root`\r\n\r\n```ts\r\nexport type LocalState = {\r\n type: string\r\n // objects and parent are used when children are added with `attach` instead of being added to the Object3D scene graph\r\n root: TresContext,\r\n objects: Instance[]\r\n parent: Instance | null\r\n primitive?: boolean\r\n eventCount: number\r\n handlers: Partial\u003CEventHandlers>\r\n memoizedProps: { [key: string]: any }\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.",[3099],{"name":3100,"color":3101},"v4","7980EA",516,"LocalState for custom renderer node instances instead of userData","2024-04-03T06:58:19Z","https://github.com/Tresjs/tres/issues/516",0.73893565,{"description":3108,"labels":3109,"number":3117,"owner":3025,"repository":3026,"state":3081,"title":3118,"updated_at":3119,"url":3120,"score":3121},"**Describe the bug**\r\nWhen use `useTres` composable inside a sub-component to obtain the state, this state never gets updated. Curiously it does get updated when accessed from `cientos` or any other package\r\n\r\n**Reproduction**\r\nPlease provide a link using this template on [Stackblitz](https://stackblitz.com/edit/tresjs-basic-trxx6f?file=src/components/TheSphere.vue) \r\n\r\n**Steps**\r\nSteps to reproduce the behavior:\r\n1. Go to reproduction link\r\n2. Open console.\r\n4. See that the console inside of the sphere gives a default state with mostly all undefined, but the console on the parent using templateRef `context` is updated with the correct value of state\r\n\r\n**Expected behavior**\r\nState using `useTres` should provide correct updated state\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: (3) 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: 9.4.2 - /usr/local/bin/npm\r\n npmPackages:\r\n @tresjs/cientos: ^2.0.0-beta.3 => 2.0.0-beta.3 \r\n @tresjs/core: ^2.0.0-beta.9 => 2.0.0-beta.9 \r\n vite: ^4.2.2 => 4.2.2 \r\n```\r\n\r\n**Additional context**\r\nAdd any other context about the problem here.\r\n",[3110,3113,3116],{"name":3111,"color":3112},"bug","d73a4a",{"name":3114,"color":3115},"help wanted","008672",{"name":3078,"color":3079},209,"useTres doesnt get updated on subcomponent","2023-04-19T08:01:20Z","https://github.com/Tresjs/tres/issues/209",0.7532037,{"description":3123,"labels":3124,"number":3128,"owner":3025,"repository":3026,"state":3081,"title":3129,"updated_at":3130,"url":3131,"score":3132},"Add the scene to the state for `cientos` to consume",[3125,3126,3127],{"name":3111,"color":3112},{"name":3037,"color":3038},{"name":3078,"color":3079},160,"[v2] - Add scene to state","2023-03-22T14:14:27Z","https://github.com/Tresjs/tres/issues/160",0.75425917,["Reactive",3134],{},["Set"],["ShallowReactive",3137],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$f_gO4DUjdT4ahS1572BAb-Uqc4v8Eku4Elotc9vFHSCk":-1},"/Tresjs/tres/37"]