jeffeb3 / sandify

web based user interface to create patterns that could be useful for robots that draw in sand with ball bearings.
MIT License
187 stars 34 forks source link

Integrate Turtle #15

Open jeffeb3 opened 7 years ago

jeffeb3 commented 7 years ago

We need to merge turtle into sandify. How do we do that?

1) Make turtle another input mode, similar to the Transforms.js. We could bring back the ace.js editor, and the command line and remove all references to the canvas from turtle, but make the output an array of vertices. -The design you have won't look the same because there's no way to lift the pen with an array of vertices. We could add a member to the Vertices to indicate a move vertex.

2) Make turtle handle the canvas, and have it use an array of vertices as input.

jamesd256 commented 7 years ago

I've taken a look at MachinePreview.js, and see you're using a canvas.

Please forgive me if I tell you stuff you know or seem obtuse, but I'm keen to resolve this now.

I think it would be useful to reset what we mean by turtle.js before I start. So there is turtle as it exists as a project on GitHub, with a nice demo. This uses 2 canvases, one for the pointer and one for the lines. There are some methods for translating logo style commands to canvas native operations. And there is an editor, and a command line interface.

There is nothing stopping us taking the methods out and adapting them to your canvas. If we want to ban penup(), we can do that, it's very simple. Or we can leave it in and just allow the Gcode to not do penup()

So the turtle drawing methods would existas a way to let people edit fun scriptlets (ace.js?), but that could be seen as an 'expert' mode for people who want to add and share shapes using a simple set of child proof methods.

So all I think we should keep here is that there is a canvas somewhere, I was also thinking of a single global canvas that the various modules all write to, and that the turtle methods should write to that canvas. If then the generate gcode button derived the vertices from that global canvas I think it would all be fine.

jamesd256 commented 7 years ago

So the turtle component would not be responsible for rendering the canvas, but instead would be passed, or would read the context of the global canvas. There would be a slight adaptation of the code so that it doesn't need 2 canvases as it does now.

The basic interface would be that turtle is a tab where some shapes (pre-defined turtle scriptlets) exists to choose from, and experts can create new ones or clone and modify existing ones. We could have a simple convention so that scriptlets with parameters would have interface controls generated to parameterise them.

jeffeb3 commented 7 years ago

It doesn't make sense to make the turtle code draw anything on the canvas, but rather communicate with the machine preview through the vertices interface. The MachinePreview's promise is that it will faithfully draw what will show up on the machine, as best it can. Having other components able to draw arbitrary items on the canvas will end up in headaches when the gcode doesn't match the display.

Looking through the turtle.js (either the original, or your Turtle.js) it looks like it would be greatly simplified if it would just remove all references to any canvas, and instead append vertices to the App.state.vertices. If there are any improvements to the drawing that you'd want, adding them to the MachinePreview will improve the drawing quality for everyone (such as figuring out how to display multiple layers, or time).

For me, turtle is a language specification. It adds value to sandify by allowing programatic shapes, while not being intimidating for people who don't write software. I'd like to see a place where people can write in the turtle language, and have the output go through the same pipeline as the other input modes. Those parts of the pipeline are:

jamesd256 commented 7 years ago

What you say makes a lot of sense. We agree about the value of turtle, it's about accessibility.

I see why you want to control the drawing centrally. You are right. I wanted to do textured lines to make the drawings appear like they will on the machine, and there is no point in doing that just in the turtle module.

Ok, great, I am happy take that as a next step. I'll have a closer look at how your interface can accept the vertices, and how I can adapt the turtle component to write to them.

jeffeb3 commented 7 years ago

I took over your branch. I made a turtle_alone branch, which is before I started messing with it. All I've done so far is inserted a \<Tabs> element. I started looking at the state, and I decided not to mess with it until I get some time for redux. I'm hoping I'll get to that today, but you know... Schedules...

jamesd256 commented 7 years ago

Good to hear. Looking forward to seeing how you get on.

jeffeb3 commented 7 years ago

I got somewhere. Things are basically using redux. In the turtle_integration branch, I've moved a few things around. I'll have some more moving before I'm finished, but if you touch the controls on the transform tab, or the controls on the turtle tab, the drawing will draw one or the other, and it's being limited by LimitsEnforcer. It's a bit of progress.

I like that we have some decent segmentation to the code, with inputs separate from each other and separate from the main pipeline and display stuff. I tried to mimick that with redux and their combineReducers, but I couldn't figure out how to reset the main vertices from inside the reducer of the inputs, so I ended up dumping everything back into one big pile of a reducer. If you have any thoughts on this, I'd appreciate it. The reducer/Index.js is a mess, IMO. Maybe that's just the cost of doing business this way. I also ended up doing a lot of building of connect methods, which seemed like a lot of boilerplate.

Maybe I can use the BaseInput to separate the input code from some of the messy parts of redux from someone wanting to make their own input. Currently, it's pretty intimidating with all this redux/react stuff everywhere.

Changing tabs doesn't actually do anything different, but when you change any of the settings, the active tab will redraw. I need to find a clever way to fix that.

Lastly, I'm pretty sure your intention was for other people to be able to write turtle scripts, not just the demo() one with the sliders, right? So I should work on getting the ace.js back into this somehow?

jamesd256 commented 7 years ago

It's good that you implemented Redux I think. It probably seems like a complexity cost and overkill, but I think it will help with scaling the app.

Seems there is an issue to sort out about the frequency of state updates - maybe operate on local props for some stuff - I need to look at the code, I'm just guessing. The issue is that moving the bottom sliders which are the most intense, gets bogged down quite badly now compared to before.

I also think it's worth smoothing out the full interface between the inputs and the rendering. I would like to take a look closely at that, which I will prioritise. I am quite interested to learn an elegant way to do redux for myself, so I can keep my developers in check.

I parked any thinking about the BaseInput until you'd got to this stage, so I will do some more reading and thinking about how best to do this.

By all means go for introducing ace. I kind of had plans to carry on working on turtle so I could do presets and persistence as discussed using RdbHost. Ace will be part of that for sure. I have started implementing a test harness of just the DB stuff.

I like the idea of DB access with no server side code. It's clever the way they've got this working, and means we can carry on being hosted on Github, have a domain name, and logged in users who can store and retrieve their own as well as other people's scenes.

It's good if we keep communicating about areas of interest, because I don't want to duplicate your work or vice versa.

One more thing, as this thread is now more architecture than integration, I have been thinking about the facility to compose a scene from multiple inputs, and also multiple instances of one input.

The idea is that inputs become abstract until someone instantiates one into the scene draw pipeline. So I could add a jeff's shape scene, then add a turtle on top, then another turtle on that. I'm thinking that there will be an input module just for doing wavy/zig-zag line/fill patterns that will be a base for more complex shapes.

jeffeb3 commented 7 years ago

w.r.t. performance, I'm pretty sure it's because I'm adding each vertex via redux, one at a time in the turtle code. I think it will be simple to save the vertices in ReduxTurtle, and then publish them at the end instead.

jeffeb3 commented 7 years ago

I read this before I had coffee this morning. I didn't understand any of it. After looking at it again, I agree with you. Let me do 2 quick things, 1 - I'll make the tabs choose the right set of vertices and 2 - I'll make the turtle code only call once to set the vertices. Then you can have it and I'll either work on the Ace or the Limits stuff again.

w.r.t. the db, can we easily do something similar to how craigslist or http://coliru.stacked-crooked.com/ does, where the url is the secret, and not the username/passwords? I just am worried about security and stuff like that. Unless you want to login using google OAuth or something like that.

As for the layers of inputs, and such, I think that's a great idea. I'm still going to fix the tabs, because I'm hoping to deploy this tonight, but having a list of inputs, and performing them in sequence is a good idea. We'll have to work on visualization and also the "segway" between paths, but that's a better way to do it.

jamesd256 commented 7 years ago

Thanks - good effort again.

I will not put any authentication in unless it's 100% industry standard. I am moving away from RdbHost, which looks fine, but it's just not something I'm used to. I've found that Heroku do full node.js hosting with a free database, within limits. I think I'd like to pursue this approach as things stand.

The ideal would be federated logins available (google+, fb, twitter, etc.) with a fallback to storing and encrypted password in a standard way, with the best of breed NPM modules.

There is a question about how the interface would work, but I would think the tabs will stay at least. I would like to work on loggin in and storing / retrieving / sharing patterns first, with some presets available for each input. Following that I guess me or you could look again at the input sequencing. If you get there first, that would be awesome too.

Just for fun I deployed to GH pages with a TLD: www.sandify.tk.

It's a free domain. Once I"m back to the workstation I'll pull the latest gh-pages from jeffe3b to that page.

That will move to Heroku soon.

jeffeb3 commented 7 years ago

sandify.tk, cool!

The logins are fine. I guess that's what people expect to see. I'm not sure we'll ever get more than 100 users though. I worry about the maintenance of the industry standard because you know in 18 months something will change and we'll need to upgrade to XYZ from YZX. The url key at coliru can be confusing to some people, I guess.

jamesd256 commented 7 years ago

Ok, well I'm happy to worry about that if you're happy to let me. Authentication systems are part of my daily bread. It's clever stuff actually. Federated logins are cool, and Scrypt is cool because it's very future proof.