Create an internal CadHub IDE for future CAD package integrations #218
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Getting the container internalized is the first step in converting the IDE. After this step instead of hosting the CascadeStudio editor wholecloth, each of its editor's panes will be hosted within our IDE layout manager. This also allows us to use a more React-ecosystem solution for layout management than the
golden-layoutpackage they use.I've been looking around for layout manager replacements more in the React ecosystem and found these three that seem promising:
I ordered them in apparent maturity and adoption. Grafana and AWS Cloudfront use React-Grid-Layout so I'd like to explore it first if that's cool.
I've had a quick look at them and starting out with the most mature makes sense ☑️
From looking at the demo of
react-grid-layout, the showcase demohttps://strml.github.io/react-grid-layout/examples/0-showcase.html
shows a static window, good to see there are features like that in case we want to be opinionated with some part of the layout and lock it in place (not saying we will, just good it's there).
Two things come to mind:
question around persisting the layout, after giving some thought I definitely think we should just have a default layout that the user can change, but just snaps back to default with a refresh, and maybe down the track we can look into persisting layouts if users are asking for it, it seems like there are too many edge cases for us to get it right without feedback eg If we are persisting do we persist the layout per part of the same layout for that user, if you edit someone else part and tweak the layout should we save that too?
I doubt using one of these grid layouts will be a problem, but it doesn't work out. I would also be happy with a fairly simple split pain layout that only has resizing between the two panes. The codersandbox layout is pretty simple after all.
I agree with both your points. Deciding policy and logic around saving layout will take some time so I think that should be a much later initiative. Yeah that's a good point if this avenue doesn't work a split pane solution will cover for a long time I bet.
I have a rough implementation using
react-grid-layoutthat shows an instance of@monaco-editor/reactin the left pane of the layout and 2 dummy frames to the right. @Irev-Dev should I push these to anidebranch on here so you can see my progress?I'm a little stuck on how to get CascadeStudio isolated to just one pane of the layout. The
CascadeView.jsfile appears to be decoupled but really isn't, as it assumes an API for the view's container that is very specific togolden-layout(see this line for an example). I don't want any of the layout logic withinCascadeView.jsbut want all the rendering and WebGL handling that's in there. I'm not sure what would be best, create a wrapper for the container that has those specific methods that this folder expects?I've created an
idebranch where progress can be tracked.I've had a quick look at your branch. I'm guessing you didn't start making as changes to the CascadeStudio submodule? You've looked at
CascadeView.jsbut not made any changes yet?Yeah exactly @Irev-Dev I was looking for a way to integrate without making changes to their code, just stuff outside it. But had their already been modification to these files? Because then I can go ahead and make it work with a few more, and we can figure out a solution with less technical debt in a bit.
Yeah I could have made this clearer, (submodules don't make it super clear where the submodule comes from),
but basically my fork of CascadeStudio is here, and there are two important branches in the fork,
kurt/webpackandcadhub-fork.kurt/webpackis the branch that's in PR on cascadeStudiocadhub-forkis the branch that checkout out in Cadhub (that's what we're using atm)Originally I didn't want to start using the webpack work in Cadhub until it got merged (incase it didn't) but ultimately I decided that it was worth using if it didn't get merged as the integration without it was so much more hacky, and I had bugs, for one thing I had a race condition that I couldn't solve, basically if open the website on the homepage then navigated to the IDE evenything worked fine, but you when directly to IDE, or refresh on the IDE, the part would never generate I think because the order things loaded. Because so much loaded with just
<srcipt src="" />s in theindex.htmlthey couldn't be controlled in the same way when your using modules/bundling.Wanting to stay away from modifying CascadeStudio makes sense, but we may have to. There has been some progress on my webpack PR so it's probably best to wait and see what happens there. Having said that if you do start hacking on the CascadeStudio code, you'll become more familiar with how it hangs together and that mightn't be a bad thing.
Ah great thank you for the explanation! I was confused by the two branches, that's all understandable.
@Irev-Dev just an update, yesterday I started messing around with the possibility of editing
CascadeMain.jsand the other CascadeStudio state management pieces to make them work. I do think we'll need to do something of that sort, because it really does seem like they're all very interdependent other than CascadeWorker which is nicely decoupled, I was struggling even when allowing myself to edit directly. Worse comes to worst I think we can rewrite the initialization code and just work with the Worker pieces.Although like you mentioned on Discord, I'm wondering if instead of working to get CascadeStudio working, I should pause this and start a Discussion about what API and features we want on the CadHub editor generally speaking? I have learned a fair bit about the events it needs to handle from digging in CascadeStudio, which I bet you have more insight into after explore the OpenSCAD integration and your work on CascadeStudio.
I can move this over to a Discussion if that's better, just need to get my initial thoughts on this editor's API down:
Layout
Managed by
IdeContainercomponent, which employsreact-grid-layoutEditor
Managed by
IdeEditorcomponent (TODO), which employs@monaco-editor/reactViewer
Managed by
IdeViewercomponent (TODO), which hooks into each CAD package via a tailored controller within/helpers/cadPackages/{cadePackageName}(maybe? open to other directory structures).Console
Managed by
IdeConsolecomponent (TODO), which is a standard React componentLet me know any thoughts that gives you! I might be playing fast-and-loose with the term "hook", "event" might be a better term. The aim of this is to find a regular API to target when integrating any new CAD packages, like we don't care how they make it happen, but each of those events should be handled by the CAD package's controller script.
Nice, that's more or less how I was thinking about it. With input/callbacks like that we should be able to swap out the Cad-package pretty easily. Here's my visual interpretation

lol I missed a line going from the editor the kernal with "code change".
It's ignoring initialisation, but Basically the the Cad-kernal acts like a pure function taking code and spitting out a health or error payload, where the cad-kernal can be openscad, CascadeStudio, whatever, we'll just do what ever wrapping we need to, to make it has the same interface. Under the hood the openscad kernal can hit an endpoint and the cascadeStudio can fire off a worker, but the rest of the IDE doesn't have to care about how it's returning the result.
It might get a bit more complicated with multiple files, but I only in payload not conceptually, and if we ever do get interaction between editor and 3d (highlighting when mousing over the other) we'll have to add that, but I don't think that invalidates anything here.
I am a little confused by all the
onXonly because I normally readonXas a callback for components to send data back up the tree, butonErrorin the Console section for example is just a data prop? Maybe it does need to be an event since the logs should accumulate. About to eat, I'll have another look later.I've had a bit of my own take, More because I was a little confused rather than thinking it's bad. Overall structure makes sense though. Having gone through it again I guess one thing that feels like it's missing is where the state for all this is. I mentioned previously that I haven't used any state-management tools yet since most of the app is pretty CRUD like (besides cascadeStudio itself which handles itself, I guess the CascadeController was a tiny little state manager on top), but maybe the IDE does need it since it's a very interactive part of the app. Though happy to start with the simple things that come with react like context and maybe useReducer. I think the state that overall ide component would manage would be nothing more than currentCode, logs for the console and last render?
Editor
Managed by
IdeEditorcomponent (TODO), which employs@monaco-editor/reactViewer
I've just remember something about openscad, I'll add something to the bottom
Sounds like your proposing a viewer for each package, I was thinking we could use the same one, so long as we abstract the interface for each Cad-kernal to be the same (but I'll admit this idea immediately breaks on the first example (openscad))
Console
Managed by
IdeConsolecomponent (TODO), which is a standard React componentnot sure about the
onpart of these, I'd probably lean towards these messages being handled by a parent components state and it would take a single prop that's an array of objectsOpenSCAD Viewer
Openscad can get real slow real fast if your trying to render out an stl for each code-change, but it's quick to produce images (I think this is because they use the CPU and GPU respectively), so I think the only way for it to be a live editor (and not chew in server costs) is for it to be image based, ie the kernal sends back images which obviously breaks the viewer above so maybe we need to build something a little more bespoke for the openscad viewer. (but fine if we go with your idea if a viewer per package)
There's also the problem with the fact that it no longer feels 3d since the user can't drag the view around, I have a UI idea for how to make this a bit better, keen to hear your thoughts on it.
This doesn't have to be part of the mvp, but I think this works because it's a) it's intuitive in the way it leads the user down the path with first semi-transparent to full transparency on click and b) the cube should act as a reference for when they want to change view.
This should be possible from the arguments I can see for the openscad command line tool.
Excellent thank you for all this! It definitely needed help:
errorandhealthystatus is definitely the way to go.onthing while writing, but not all things are event callbacks lol.object(or maybeobjectData)? Just wondering if it should be image data ready to paint by that point or data to pass into a ThreeJS instance, because that'll hit a bump with OpenSCAD Viewer right? Or does the viewer default to accepting ThreeJS data unless swapped out like in the OpenSCAD case?IdeConsolemakes so much more sense like that, thank you.Yoo I love that interaction idea for the OpenSCAD Viewer! I'd love to think about how to represent pan and zoom in addition. I think having a Look At button could be really helpful for people to quickly get reoriented without access to the immediate feedback of a 3D viewer.
Let use use reducer, I'm happy to not pull in extra dependencies for the time being. I think that will mean that we won't be using props and callbacks, but instead consuming state and dispatching, but same conceptually as input output of each component.
I'm not exactly sure whats in
objectData. It probably needs to be a little flexible since the input the viewer is probably not going to be 100% unifrom, ie CadQuery can ouput in three.js formate, where as openscad exports will be stl and maybe images. Could be just{type: 'stl', data: 'binary or whatever it happens to be'}Yup we might have the a tool bar still, might be worth starting fresh with this one?
I think maybe the way to move forward is the get the shells of all of these components up with nothing more than the reducer and some dumby state, with a couple buttons in each of the them to fire the dispatches for what will come proper user interactions later just as a starting point? If we put this on a new page/route that's not accessible from within the app that there's no reason we can't get that committed into master.
https://user-images.githubusercontent.com/29681384/109952868-75515280-7d33-11eb-8c1b-e4ae5e37d623.mov
I hope this is helpful and not . . . annoying and it's not supposed replace to your work if you've made a start, more as something to centre discussion around, and sometimes a bit of scaffolding for data can go a long way in helping me wrap my head around things.
I wanted to get this up tonight and regrettably I didn't have the time to go through and make the data match what we've talked about above.
https://github.com/Irev-Dev/cadhub/compare/kurt/ide-scaffold-or-ideas
some points are.
No this is perfect thank you for starting the work on this! You have a better sense of what the framework needs to look like anyway. I took a break last night and just worked on making some models within CadHub.
state.ideType. Then down in the middleware instead of callingrenderOpenScad()you could callcadPackage[ideType].render(). Apologies if that was already your plan I just wanted to see how multiple CAD packages could work.imageor something?This is so dang clean! I'm excited. I think once this thing is set up it'll be so much more straightforward to ask for dev help on. People can pick a CAD package to work on and know exactly the interface they need to target in their one controller file, right??
I just had a look at CadHub to see what you'd been working on 🤣 haha that's great 🍩 ⚙️ .
Point 5)
cadPackage[ideType].render()is exactly what I want to do. Glad we're on the same page 😁Point 3) I just realised I made a critical typo, I meant to say "can't access state", and the main reason I think that's a problem because of the above where I'd like to have
but can't. Tool like redux have ways of dealing with async (like thunks), but it less clear what to do for useReducer. I found the to be useful break down of some options. https://gist.github.com/astoilkov/013c513e33fe95fa8846348038d8fe42
I went with option 3 but the state issues didn't occur to me until I started using it.
Point 6) yup will be image and sometimes stl.
How about I change that PR so that it's not just sitting on the homepage and instead on some inaccessible route and we can get it merged that should make it easier for us both to work on different components at the same time?
And yup exactly about the controller, I'm hoping if we hit a critical mass that some of the smaller cad packages will see the benefit of integrating with us and will help out in getting their tool working with CadHub.
One other quick question, have you written any typescript?
I was thinking having state interacting in multiple files might benefit from having types.
So I put this up
https://github.com/Irev-Dev/cadhub/pull/223
I haven't written much Typescript but I understand it pretty well, just need to learn a bit more about writing those
interfaceblocks but I think that's a great idea.Ohh it can't access that state! Fascinating. I read through that post and I have a dumb question. Is there anything stopping you from passing
stateinto the middleware call likedispatchMiddleware(dispatch, state). Would cause some kind of circular dependency? Or would that maybe only have the initial state available to it?Genius, because it's a custom hook, it would get the new version of state every time it's run (I'm pretty sure), nice one 👏 .
Hey @Irev-Dev just checking through the Projects tab, would you consider this complete? So cool to read through this discussion and see the fruits of it with JSCAD and CadQuery coming to bear.
Yeah I think it's complete.
that project is probably pretty neglected hey!?