I’m having trouble getting the CameraGizmo to render using ReactJS-Babylon. As you can see in the playground above it’s a pretty simple example, but using the react-babylonjs library, it just doesn’t seem to take, I’ve tried multiple different versions of this code, but here’s the first iteration that is very similar to my working code for mesh gizmos:
<utilityLayerRenderer>
{/* add the second render camera */}
<freeCamera
name="renderCam"
position={new Vector3(0, 0, 2)}
cameraDirection={new Vector3(0,0,-1)}
scene={scene}
ref={renderCameraRef}
>
<cameraGizmo ref={gizmoRef} camera={renderCameraRef.current} />
</freeCamera>
</utilityLayerRenderer>
From what I can tell logging out the gizmoRef, the cameraGizmo camera attribute is always null, even when set from the the renderCameraRef.current, which I log out as well. The cameraGizmo.attachedNode is correctly set to the freeCamera, but it never renders.
I guess I found a solution, it doesn’t feel very reacty, but here’s code that seems to be working, we just brute force it on ever render check if we don’t have a camera and set it to the refs. Is there a more elegant way?
Looks like a bug in react-babylonjs… maybe you are the first one to try declarative camera gizmo?. The camera prop wouldn’t be set by renderer I don’t think - could use an update to the lifecycle listener to attach.
Maybe similar to how light gizmo connects should work otherwise:
Thanks for the quick reply @brianzinn. Maybe a dumb question, but is there a way to view that story in the story book like the Babylon Playground? I’m not seeing it on this page, which has been really helpful for learning React BabylonJS by example.
Another ask, how were you able to determine it was a bug with the camera prop not being set by renderer so quickly. I’ve love a bit of insight into how to track these issues down so that I don’t have to rely solely on the forums. Teach me how to fish so to speak I’m loving the package, but one of the larger points of friction is that some times its hard to translate BabylonJS into React and get it working reliably.
Any insight or code or docs to read that would be greatly appreciated!
I think I found another bug? Not sure if I’m just using the react components a way they aren’t meant to be used. The onClickedObservable doesn’t seem to be firing no matter how I set it on the component:
The console.log of gizmoRef.current shows the observable and the observer I added to it. But clicking on the gizmo doesn’t log anything, maybe I missed a setting to make the camera clickable?
I’ve added a camera and a gizmo and observerable through basic BabylonJS in my react app and it works correctly, just like the playground below. Example of this:
onClickedObservable I believe works differently than you are expecting. You shouldn’t be assigning directly to an observable property (setter).
// do not do this:
cameraGizmo.onClickedObservable = myObject;
You should be calling the add method it has instead.
gizmo.onClickedObservable.add(() => console.log);
if you are going the declarative route then it should work with just a function signature:
// you can memoize this or useCallback with dependency array, etc.
onGizmoClick = (e) => console.log;
return (
...
<cameraGizmo ... onClickedObservable={onGizmoClick} />
)
There is a link “search playground for…” - sometimes following that leads to helpful results as well.
I think that’s not entirely unexpected and the docs section for react-babylonjs is not helping. I do have a new site that will one day come online and it does explain a lot of how things really work and how to properly translate. I just cannot seem to find time to work on it - right now also the newer babylonj.js versions changed their target compatibility, so my CI/CD pipeline broke, so there won’t be any releases until I sort that out as well!
No worries! Thanks for all of your time and guidance . It’s a lot of work maintaining a project and keeping up with one as large as BabylonJS.
I was able to get the camera gizmo’s onClickedObservable working, just not through the declarative react component, I ended up removing the gizmo and creating it with regular babylon. Everything seems to be rendering and clicking is working as well. I’ll post what worked for me and mark as solution so others can hopefully benefit:
Glad that works for you. I can make a couple of small changes to react-babylonjs and this would work (right now the renderer is ignoring the camera prop):
With another couple of small changes I could do a deferred instantiation until there is a camera in the tree graph, so when you declare as a child component of a camera that it would automatically assign the camera/light. Right now that is already done, but only for attaching to node/mesh. For example, this automatically attaches a LightGizmo to a mesh and works on current version:
Thanks @brianzinn ! Yes I was referencing that exact lightGizmo example when I was setting up the cameraGizmo and I think that’s why I struggled so much with the cameraGizmo, because there needs to be that deferring step for the camera. (I actually ran into this later with some camera renderTargetTextures, my “temporary” solution was a rather ugly setTimeout)
As for adding it, it’s not urgent for me. I have a workaround solution, though I do love the declarative approach . But I realize you’re busy.
I can give you my perspective as an outside developer that the difference between how the lightGizmo and cameraGizmo worked threw me for a big loop and made me start questioning my sanity . My developer brain couldn’t get past “lightGizmo works like this, cameraGizmo has to be the same!”
If you don’t mind me asking, I thought the lightGizmo and cameraGizmo were generated by Babylon.JS types, it sounds like there is some logic happening to handle the attaching for the lightGizmo onto a mesh, do you mind sharing a link to the github where that code is for me? I wouldn’t mind digging a bit more into the inner workings to gain some more insights.
Would be super happy to have more people checking out the codegen parts.
It’s a bit restrictive, but the object properties can be assigned with an allow only list. I actually added the light explicitly for the LightGizmo. Just need two lines:
But also there are conversions to numeric arrays for the integration with react-spring, etc. Anyway, adding light is easy, but it’s getting to the point of needing a major refactor…