GlowScript style

275 views
Skip to first unread message

Bruce Sherwood

unread,
Aug 5, 2012, 5:59:23 PM8/5/12
to glowscri...@googlegroups.com
In the old forum a user asked this:

I looked at the examples and started writing an app. I had one scene, and whenever I was done displaying something I erased it all and started the next display.

Then I thought, why not just delete the scene and start with a blank one for the next display? But when I tried that, I saw no way to actually delete a scene. I could hide everything in it, but that left me with a black box on the display, and my new scene was started below the old one. I could scroll down to it.

Then I thought some more. It could actually be designed like a web page. Have a series of scenes with text between them. Scroll down like a web page. Click on one to start an animation, and click it again to stop it before you start the next animation. Or leave them all running maybe? The more you have running the slower they all get....

Say you wanted to have multiple scenes updating. Write the code that updates one and the code that updates the next and so on. Then wait for the display to redraw before you update any of them. The faster the computer it runs on, the more you can do before it starts stuttering -- but you have no control over which computers run a web page....

I just now realized that there's a lot here to design, that I don't have thought out at all. But just in case -- is there a way to delete a scene, so a new scene can fit into the same place? 

Ay ideas what sort of designs might be useful for various purposes?

I replied:

The quick answer is no, there isn't a nice way to empty a scene, though there should be. You can of course make all your current objects invisible and then draw in the same canvas rather than creating a new one. From the Help on canvases (in such a loop you could make the object invisible):

objects A list of all the visible objects in the display; invisible objects and lights are not listed (scene.lights is a list of existing lights). For example, the following makes all visible boxes in the scene turn red:

for (var obj in scene.objects)
    var o = scene.objects[obj]
    if (o.constructor == box) 
        o.color = color.red

You could also write if (o.constructor.name == 'box').

Your style questions are good ones. Here are two programs you might look at for ideas:


Jethomas5

unread,
Aug 6, 2012, 10:33:47 PM8/6/12
to glowscri...@googlegroups.com

Here is a program that's technically simple, but displays a particular style.

http://www.glowscript.org/#/user/jethomas5/folder/diffraction/program/Fraunhofer_diffraction.

It's just a web page. It has one 3D image that doesn't do anything, but could. The other images are all visible at once, along with all the text.
Why should I hide anything? If a user wants to skip down and look at something else, that's fine.

Here's what I noticed writing this and other stuff in Glowscript using Coffeescript.
First, when I didn't already know Javascript I could hardly imagine learning Javascript instead of Coffeescript. Javascript is obviously much worse. But Coffeescript does not have a tremendous amount of documentation. And the error reporting is primitive. Very often I would leave off a ) or a , or a " or occasionally a } or have an extra one. And typically the result was an error message that went "Missing ) on line 259". That is, the last line.
Sometimes it would report something completely uninformative.

I found myself running the program after every change, because if I changed only one line then if it broke I knew it had something to do with that line.

The Glowscript editor is -- primitive. For example, it has no repeat replace function. That's OK, I can copy a string into the clipboard and cntl-V it in place after I do cntl-K for repeat find. For every simple thing I wanted to do there was a workaround, I just had to find it. I think this editor might let me add my own keybindings and customize it for coffeescript, but I haven't learned how yet. I would have preferred some simple editor I was used to, but I had to run the program after every change....

I block-commented out everything I could that I wasn't working on at the moment, because it kept me from having to click on stuff or scroll past it to get to what I wanted to test. Of course, it was easy to make a simple mistake like wind up with an odd number of block-comment symbols, which would generate another uninformative error message.

It works very well. There's room for improvement in the user interface.

I would like to have a standard text output available, so I can test equations and such without having to write a utility to output them.
Better error messages would probably help new users in their first couple of hours. That's important since they might quit in the first couple of hours.
The editor is probably customized for Javascript, and a version customized for coffeescript would be good.
If there's a way to get the LaTex thing to operate on text strings first, then it wouldn't need all the \ to be doubled. That would be quite a convenience.

I'm very pleased with it. It isn't as easy to use as VPython, but it makes things that are like web pages that run in browsers, which VPython does not.

Bruce Sherwood

unread,
Aug 8, 2012, 4:12:12 PM8/8/12
to glowscri...@googlegroups.com
A tiny style suggestion for your diffraction program would be to set scene.forward for the first (3D) display, to look down slightly on the scene. Initially I didn't try rotating the camera and misunderstood what I was looking at. Looking slightly down shows the red sheet of light emerging from the slit.

Incidentally, this is an example of something Ruth Chabay and I discovered experimentally. Physics textbooks often show a 2D view of some 3D object, and the skilled reader supplied a third dimension into the page. We found that this skill is not something the novice necessarily has, and that it really helps to give a 3D view to provide the context for the 2D slice.

I agree completely with the problems of editing and debugging CoffeeScript programs, and I'm working on this. The ACE editor used by GlowScript can support CoffeeScript, and I'm trying to learn enough about ACE (and its GlowScript context, which David Scherer implemented) to switch to CoffeeScript mode if that's the language you've specified on the first line of your program. Assuming I can do this, there remains the question of whether there will remain problems of useful error reporting.

I also agree that a scrolling text object would be very useful in GlowScript. For all I know, one can create one using jQuery right now, but I haven't searched for this. I will mention some other workarounds.

* alert('The mass is '+m+' kg.')
This pauses execution and displays the string in a dialog box. Numeric values are converted to strings.

* $('body').text('This is a test.')
Use this to output text if you do NOT create any 3D objects.

* console.log('This is a test.')
This requires opening the browser's "console". For example, in Chrome, press shift-ctrl-j.

* Of course you have scene.title.text('A TITLE') and scene.caption.text('See?').

"If there's a way to get the LaTex thing to operate on text strings first, then it wouldn't need all the \ to be doubled. That would be quite a convenience." Maybe the way to do this is with a function that does the doubling. Not clear.

Jethomas5

unread,
Aug 10, 2012, 11:27:37 AM8/10/12
to glowscri...@googlegroups.com


On Wednesday, August 8, 2012 8:12:12 PM UTC, Bruce Sherwood wrote:
A tiny style suggestion for your diffraction program would be to set scene.forward for the first (3D) display, to look down slightly on the scene. Initially I didn't try rotating the camera and misunderstood what I was looking at. Looking slightly down shows the red sheet of light emerging from the slit.

Incidentally, this is an example of something Ruth Chabay and I discovered experimentally. Physics textbooks often show a 2D view of some 3D object, and the skilled reader supplied a third dimension into the page. We found that this skill is not something the novice necessarily has, and that it really helps to give a 3D view to provide the context for the 2D slice.

Thank you! Incidentally, one of the things I like  lot about Glowscript is that I can easily zoom and rotate whenever I feel like it. Things get a lot clearer, except that it feels like the perspective is *wrong* when nearby objects get very large. When I don't want that I change  the range and fov to minimize it. I'm glad to be able to have that go either way.

One thing that has gotten in my way is not having any easy way to get the picture back the way it was before I messed it up. Sometimes there is an important way to look at things, and once I lose it I can never get it back exactly. The labels that don't turn with the picture help. I wound up setting it up so that when I change a canvas after it's been paused, I reset it to its original orientation. That helps a lot for the sort of thing I've been doing. But the ideal would be for the final user to be able to set it back whenever he wants. Possibly with a keystroke, or with a button off-canvas.


* alert('The mass is '+m+' kg.')
This pauses execution and displays the string in a dialog box. Numeric values are converted to strings.

That works! I will use it for debugging, it's easier than what I was doing.
 
* $('body').text('This is a test.')
Use this to output text if you do NOT create any 3D objects.

That works for me.
 
* console.log('This is a test.')
This requires opening the browser's "console". For example, in Chrome, press shift-ctrl-j.

This does not work for me in Firefox with my hardware and my version of Linux. Shift-ctrl-j gives me an error console that lists a lot of warnings even when it runs GlowScript 1.0 with no further commands. Presumably there's something a little bit wrong with my Javascript, but it runs. I get nothing but those warnings, ever. It would be great if I could dump debug data to the console without much formatting, so I'll look for a way to do that.  I can do shift-ctrl-k to get a second error console that I can't seem to actually get anything to print in yet.

"If there's a way to get the LaTex thing to operate on text strings first, then it wouldn't need all the \ to be doubled. That would be quite a convenience." Maybe the way to do this is with a function that does the doubling. Not clear.

Yes. I could write a simple offline routine that would search for Latex and add the \ that aren't already doubled. I'd only have to move the text back and forth once for each time I wanted to update that. I have tried to avoid that sort of thing because if I download text to my own editor and then make multiple changes, then when I try to run the code I have to track down the errors by hand, often it refuses to run and says there is an error at the end. If I run it after every change then I know the error is connected to the last thing I changed. But if it was only for displaying LaTex that wouldn't be so bad. LaTex errors usually just show up as text that doesn't look the way I want it to.

I kind of feel like apologizing for bothering you with newbie problems that I can eventually solve for myself. But other people might have similar issues.

Bruce Sherwood

unread,
Aug 10, 2012, 11:58:34 AM8/10/12
to glowscri...@googlegroups.com
Don't apologize! Your comments are very useful. And at the moment, we're ALL newbies, including me.

Here's a better version of basic output:

box()
$('body').append('This is a test<br>')
scene.pause(wait)
$('body').append('After the first output')

On Firefox on Windows, if I click the "Firefox" menu, choose "Web Developer", then "Web Console", then run 

console.log('This is a test.')

I get lots of debugging stuff, but the final output is "This is a test." This also works for me on Ubuntu, using Tools > Web Developer > Web Console.

I should add this output stuff to the documentation.

Jethomas5

unread,
Aug 14, 2012, 11:12:08 PM8/14/12
to glowscri...@googlegroups.com


On Friday, August 10, 2012 3:58:34 PM UTC, Bruce Sherwood wrote:

On Firefox on Windows, if I click the "Firefox" menu, choose "Web Developer", then "Web Console", then run 

console.log('This is a test.')

I get lots of debugging stuff, but the final output is "This is a test." This also works for me on Ubuntu, using Tools > Web Developer > Web Console.

I should add this output stuff to the documentation.

When I did it just the way you said, it worked for me on TinyCore with Firefox. I'm not sure what I didn't do right before. Possibly I didn't have the right window open before I ran the code.

 

Jethomas5

unread,
Aug 14, 2012, 11:32:01 PM8/14/12
to glowscri...@googlegroups.com

I tried to write a short tutorial. It covered several simple topics that built on each other. It seemed natural to me for them all to be laid out on a webpage, so the user could look for whatever he wasn't clear about and zero in on that. I didn't like having to start at the beginning, and go forward in lockstep. I didn't like having a complicated menu system to navigate.

Some of my canvases had animations. I wanted users to be able to click on one to start it, and then click on it again to stop, and click on it again to restart it.

Following the example code it was easy to write an animation that kept going until the user clicked on it. But when I try to go much beyond that I find I'm unclear on the concepts.

It looks like the mouse bindings will run whenever their events happen. Probably they should do something quick, like set a flag for other code to read.
But when does the other code run? I can set up a loop that appears to run forever, does it multitask with all the other tasks on other canvases that appear to run forever?
If one of my loops stops, can I start it again when a mouse or keyboard event says to?

Should I put all my loops inside a big loop that starts them depending on -- what canvas got clicked on? Is a canvas a clickable object?

I'm getting some ideas just by writing this down. But is there further documentation? Would the VPython documentation give some clues? Am I trying to do something that just won't work?

Bruce Sherwood

unread,
Aug 15, 2012, 2:01:02 AM8/15/12
to glowscri...@googlegroups.com
There are no threads or interrupts. If your program has an infinite
loop, with no scene.pause or sleep or rate to permit processing of
mouse or keyboard events and rendering of the current state of your 3D
objects, the web page will be frozen, because JavaScript doesn't
implement interrupts or threads. You won't even be able to zoom or
rotate.

Mouse clicks indeed go to the canvas where you click. You bind mouse
events to specific canvases, as is shown in the documentation and
various demo programs. The standard scheme is to have the bound mouse
routine set a flag that your program looks at.

I think I mentioned it before, but here's my stab at a tutorial
(albeit with just one canvas):

http://www.glowscript.org/#/user/Bruce_Sherwood/folder/Pub/program/NeutronDecay

Also, the rug program in the Example programs, which you've built on,
has the option to start and stop the animation by clicking on the
canvas.

Jethomas5

unread,
Aug 15, 2012, 8:38:54 AM8/15/12
to glowscri...@googlegroups.com


On Wednesday, August 15, 2012 6:01:02 AM UTC, Bruce Sherwood wrote:
There are no threads or interrupts. If your program has an infinite
loop, with no scene.pause or sleep or rate to permit processing of
mouse or keyboard events and rendering of the current state of your 3D
objects, the web page will be frozen, because JavaScript doesn't
implement interrupts or threads. You won't even be able to zoom or
rotate.

OK! I can work with that. So what you have is a sort of multitasking they used to call "round robin". Each process gets control and keeps it until it lets go. There's a sort of monitor program that doesn't interrupt anything. When the current routine quits, then the monitor decides what to run next. If a bunch of routines each have an infinite loop, and they quit and wait until the next page update, then the monitor program marks time until the page update happens. If the page update has already happened because they ran too long, then it just starts running them immediately.

I could have many cavases that each have an infinite loop and some sort of wait, and they can all run at once. If they take too long they will lag. I can click on one to set a flag that tells it to stop drawing, and it still runs and checks the flag! An interrupt system would let me give them priorities and just not run the ones with lowest priorities instead of slowing down the others. But I don't need that. This way is simpler.

I was confused because I had the loop stop, and then I didn't know how to start it again.

Mouse clicks indeed go to the canvas where you click. You bind mouse
events to specific canvases, as is shown in the documentation and
various demo programs. The standard scheme is to have the bound mouse
routine set a flag that your program looks at.

OK! I was a little confused by the place in the documentation it said "Although a canvas such as scene must be mentioned, keyboard events are associated with the web page, not with a particular canvas." But the point is, I can click on a particular canvas to set one particular variable, and click on another canvas to set a different variable. Even if the events are associated with the web page, I can get specific actions that won't interfere with each other.
 
I think I mentioned it before, but here's my stab at a tutorial
(albeit with just one canvas):

http://www.glowscript.org/#/user/Bruce_Sherwood/folder/Pub/program/NeutronDecay

Also, the rug program in the Example programs, which you've built on,
has the option to start and stop the animation by clicking on the
canvas.

I think I can take it from here, at least until I get confused again. Thank you!
 
Now I will find out whether the project I want to do will use too many resources by building a big web page, when it might use fewer by building separate pages that link to each other. You showed how to provide links, just by making text that's HTML and putting the links into it. So I should be able to easily link to other GlowScript programs though they can't share information. Smooth!

That may give one way to get around the 65536 node/program limit too. If each separate GlowScript program can have 65536 nodes, that makes the limit per canvas and not per project. Clicking on a link directly from a project page is better than starting a brand new program from the folder.

Bruce Sherwood

unread,
Aug 15, 2012, 10:40:29 AM8/15/12
to glowscri...@googlegroups.com
Your linking idea is intriguing. I hadn't thought of linking multiple
GlowScript programs. Note too that if the link specifies
target='_blank' the links can go into separate tabs.

I'm not sure whether you have used VPython. If you have, take a look
at the example program extrusion_overview.py, which is in the form of
a tutorial.

Jethomas5

unread,
Aug 15, 2012, 3:32:29 PM8/15/12
to glowscri...@googlegroups.com


On Wednesday, August 15, 2012 2:40:29 PM UTC, Bruce Sherwood wrote:

I'm not sure whether you have used VPython. If you have, take a look
at the example program extrusion_overview.py, which is in the form of
a tutorial.

Yes, I've liked using VPython a lot. My linux experience is not up to compiling VPython on my system. I was glad to find GlowScript that would run on my system but it doesn't do all the same things.
 
When I tried my ideas for GlowScript, it looked like it does not in fact use a round-robin multitasker. It looks like when you tell it to wait, it simply waits. That is discouraging.

I looked at writing a simple multitasker myself but I'm missing a vital command which the simple CoffeeScript tutorials I've found so far don't say how to do. I guess I'll use some clumsy workaround in the short run.

Bruce Sherwood

unread,
Aug 15, 2012, 5:06:56 PM8/15/12
to glowscri...@googlegroups.com
I don't really understand what it is that you're trying to do. Can you
be more explicit about it? I would be surprised but interested to
learn that it's not possible within the current GlowScript framework.
> --
>
>
>

Jethomas5

unread,
Aug 15, 2012, 7:57:41 PM8/15/12
to glowscri...@googlegroups.com


On Wednesday, August 15, 2012 9:06:56 PM UTC, Bruce Sherwood wrote:
I don't really understand what it is that you're trying to do. Can you
be more explicit about it? I would be surprised but interested to
learn that it's not possible within the current GlowScript framework.

I see a way to do it, it's just clumsy.

Say I have four different animations on different canvases.
I want to first draw all four canvases and all the surrounding text.
Then I want the user to be able to scroll up and down the webpage and start any animation he wants, whenever he wants.
Ideally he should stop one animation before he starts another. But if he wants to fun them all at the same time that's fine with me, just depending on his system they might slow down.

I definitely don't want him to have to start and stop the first animation before the second canvas is displayed.

I tried to copy your one-canvas examples which of course weren't designed for that.

So the obvious way to do it is:

1. display all the canvases and opening text.
2. write all the click triggers; each canvas gives the same variable a different number.
3. write one big loop that includes every canvas's animation code in a case statement or something like that.

My big loop can have an update.wait statement at the end. None of the individual canvas animation fragments need that. Or I could let them have their own wait statements, but a long wait like waitfor("click", wait) will presumably freeze everything -- others won't start if clicked on until after this one canvas has been clicked.

Only one of them runs at a time, but I didn't really need more than one running. I can do without that just fine.

I could have more than one run, though. Have each canvas mouse click toggle a variable that decides whether that animation runs once or just drops through.
Instead of choose one, just run each of them one after another and do update(wait) at the end.

It's a little inconvenient because I don't have the animation code close to the canvas code that reminds me what it's doing. But I can write it close to the canvas code and test it all by itself, and then move it to the loop later after it works right.

I have the idea that a simple multitasker would be useful, but I can get by without it long enough to get a sense of how much I need it. No matter how useful it might be for me, if most of the users don't know how to use one then it wouldn't be useful to them.

Reply all
Reply to author
Forward
0 new messages