diff --git a/labextension/vpython/src/glowcommlab.js b/labextension/vpython/src/glowcommlab.js
index 034ef61..d1bc6f6 100644
--- a/labextension/vpython/src/glowcommlab.js
+++ b/labextension/vpython/src/glowcommlab.js
@@ -537,12 +537,13 @@ function decode(data) {
vs = [Number(val[1]), Number(val[2]), Number(val[3]), Number(val[4])]
}
} else if (textattrs.indexOf(attr) > -1) {
- if (attr == 'choices') { // menu choices are wrapped in a list
- val = m[3].slice(2,-2)
- val = val.replace(/'/g, '') // remove quotes
- let s = val.split(',')
+ if (attr == 'choices') { // menu choices are wrapped in a list
+ val = m[3].slice(1, -1) // remove outer brackets
+ val = val.replace(/'/g, '') // remove quotes
+ val = val.replace(/, /g, ',') // remove spaces after commas
+ let s = val.split(',')
val = []
- for (let a of s) {val.push(a)}
+ for (let a of s) { val.push(a) }
} else {
// '\n' doesn't survive JSON transmission, so in vpython.py we replace '\n' with '
'
val = m[3].replace(/
/g, "\n")
diff --git a/vpython/vpython_libraries/glowcomm.html b/vpython/vpython_libraries/glowcomm.html
index e5a0440..da47092 100644
--- a/vpython/vpython_libraries/glowcomm.html
+++ b/vpython/vpython_libraries/glowcomm.html
@@ -347,7 +347,7 @@
} else if (obj.objName === 'radio') {
evt.value = obj.checked
evt.widget = 'radio'
- } else if (obj.objName === 'menu') {
+ } else if (obj.objName === 'menu') {
evt.value = obj.index
evt.widget = 'menu'
} else if (obj.objName === 'winput') {
@@ -362,7 +362,7 @@
}
// attrs are X in {'a': '23X....'} avaiable: none
-let attrs = {'a':'pos', 'b':'up', 'c':'color', 'd':'trail_color', // don't use single and double quotes; available: comma, but maybe that would cause trouble
+var attrs = {'a':'pos', 'b':'up', 'c':'color', 'd':'trail_color', // don't use single and double quotes; available: comma, but maybe that would cause trouble
'e':'ambient', 'f':'axis', 'g':'size', 'h':'origin', 'i':'textcolor',
'j':'direction', 'k':'linecolor', 'l':'bumpaxis', 'm':'dot_color',
'n':'foreground', 'o':'background', 'p':'ray', 'E':'center', '#':'forward', '+':'resizable',
@@ -389,35 +389,34 @@
'?':'font', '/':'texture'}
// attrsb are X in {'b': '23X....'}; ran out of easily typable one-character codes
-let attrsb = {'a':'userzoom', 'b':'userspin', 'c':'range', 'd':'autoscale', 'e':'fov',
+var attrsb = {'a':'userzoom', 'b':'userspin', 'c':'range', 'd':'autoscale', 'e':'fov',
'f':'normal', 'g':'data', 'h':'checked', 'i':'disabled', 'j':'selected',
'k':'vertical', 'l':'min', 'm':'max', 'n':'step', 'o':'value',
'p':'left', 'q':'right', 'r':'top', 's':'bottom', 't':'_cloneid',
'u':'logx', 'v':'logy', 'w':'dot', 'x':'dot_radius',
'y':'markers', 'z':'legend', 'A':'label','B':'delta', 'C':'marker_color',
- 'D':'size_units', 'E':'userpan', 'F':'scroll', 'G':'choices', 'H':'depth',
- 'I':'round', 'J':'name', 'K':'offset', 'L':'attach_idx'}
+ 'D':'size_units', 'E':'userpan', 'F':'scroll', 'G':'choices', 'H':'depth', 'I':'round'}
-// methods are X in {'m': '23X....'} available: u
-let methods = {'a':'select', 'b':'pos', 'c':'start', 'd':'stop', 'f':'clear', // unused eghijklmnopvxyzCDFAB
+// methods are X in {'m': '23X....'}
+var methods = {'a':'select', 'b':'pos', 'c':'start', 'd':'stop', 'f':'clear', // unused eghijklmnopvxyzCDFAB
'q':'plot', 's':'add_to_trail',
- 't':'follow', 'w':'clear_trail',
+ 't':'follow', 'u':'_attach_arrow', 'w':'clear_trail',
'G':'bind', 'H':'unbind', 'I':'waitfor', 'J':'pause', 'K':'pick', 'L':'GSprint',
'M':'delete', 'N':'capture'}
-let vecattrs = ['pos', 'up', 'color', 'trail_color', 'axis', 'size', 'origin',
+var vecattrs = ['pos', 'up', 'color', 'trail_color', 'axis', 'size', 'origin', '_attach_arrow',
'direction', 'linecolor', 'bumpaxis', 'dot_color', 'ambient', 'add_to_trail', 'textcolor',
'foreground', 'background', 'ray', 'ambient', 'center', 'forward', 'normal',
- 'marker_color', 'offset']
+ 'marker_color']
-let textattrs = ['text', 'align', 'caption', 'title', 'title_align', 'xtitle', 'ytitle', 'selected', 'capture', 'name',
+var textattrs = ['text', 'align', 'caption', 'title', 'title_align', 'xtitle', 'ytitle', 'selected', 'capture',
'label', 'append_to_caption', 'append_to_title', 'bind', 'unbind', 'pause', 'GSprint', 'choices']
// patt gets idx and attr code; vpatt gets x,y,z of a vector
-const patt = /(\d+)(.)(.*)/
-const vpatt = /([^,]*),([^,]*),(.*)/
-const quadpatt = /([^,]*),([^,]*),(.*)/
-const plotpatt = /([^,]*),([^,]*)/
+var patt = /(\d+)(.)(.*)/
+var vpatt = /([^,]*),([^,]*),(.*)/
+var quadpatt = /([^,]*),([^,]*),(.*)/
+var plotpatt = /([^,]*),([^,]*)/
function decode(data) {
"use strict";
@@ -429,12 +428,12 @@
var ms = []
if ('attrs' in data) {
- let c = data['attrs']
+ var c = data['attrs']
for (i=0; i -1) {
- if (attr == 'choices') { // menu choices are wrapped in a list
- val = m[3].slice(2,-2)
- val = val.replace(/'/g, '') // remove quotes
- let s = val.split(',')
+ if (attr == 'choices') { // menu choices are wrapped in a list
+ val = m[3].slice(1, -1) // remove outer brackets
+ val = val.replace(/'/g, '') // remove quotes
+ val = val.replace(/, /g, ',') // remove spaces after commas
+ let s = val.split(',')
val = []
- for (let a of s) {val.push(a)}
+ for (let a of s) { val.push(a) }
} else {
// '\n' doesn't survive JSON transmission, so in vpython.py we replace '\n' with '
'
val = m[3].replace(/
/g, "\n")
@@ -542,7 +542,6 @@
*/
-
if (data.cmds !== undefined && data.cmds.length > 0) handle_cmds(data.cmds)
if (data.methods !== undefined && data.methods.length > 0) handle_methods(data.methods)
if (data.attrs !== undefined && data.attrs.length > 0) handle_attrs(data.attrs)
@@ -569,7 +568,7 @@
var vlst = ['pos', 'color', 'size', 'axis', 'up', 'direction', 'center', 'forward', 'foreground',
'background', 'ambient', 'linecolor', 'dot_color', 'trail_color', 'textcolor', 'attrval',
'origin', 'normal', 'bumpaxis','texpos', 'start_face_color', 'end_face_color', 'marker_color',
- 'start_normal', 'end_normal', 'offset']
+ 'start_normal', 'end_normal']
if ((obj != 'gcurve') && ( obj != 'gdots' ) ) vlst.push( 'size' )
var cfg = {}
var objects = []
@@ -723,14 +722,7 @@
}
break
}
- case 'local_light': {
- let g = glowObjs[idx] = local_light(cfg)
- if (cfg.offset !== undefined) { // mocking up attach_light
- g.__obj = glowObjs[cfg.attach_idx]
- g.canvas.attached_lights.push(g)
- }
- break
- }
+ case 'local_light': {glowObjs[idx] = local_light(cfg); break}
case 'distant_light': {glowObjs[idx] = distant_light(cfg); break}
case 'canvas': {
if ((typeof isjupyterlab_vpython !== 'undefined') && (isjupyterlab_vpython === true)) {
@@ -757,6 +749,19 @@
// Display frames per second and render time:
//$("").appendTo(glowObjs[idx].title)
}
+ case 'attach_arrow': {
+ var attrs = ['pos', 'size', 'axis', 'up', 'color']
+ var o = glowObjs[cfg['obj']]
+ delete cfg['obj']
+ var attr = cfg['attr']
+ delete cfg['attr']
+ var val = cfg['attrval']
+ delete cfg['attrval']
+ if (attrs.indexOf(attr) < 0) attr = '_attach_arrow'
+ o.attr = val
+ glowObjs[idx] = attach_arrow( o, attr, cfg )
+ break
+ }
case 'attach_trail': {
if ( typeof cfg['_obj'] === 'string' ) {
var o = cfg['_obj'] // the string '_func'
@@ -788,13 +793,10 @@
break
}
case 'radio': {
- cfg.canvas = canvas.get_selected()
- cfg = fix_location(cfg)
- delete cfg.canvas
cfg.objName = obj
cfg.bind = control_handler
+ cfg = fix_location(cfg)
glowObjs[idx] = radio(cfg)
- // glowObjs[idx].canvas = canvas.get_selected()
break
}
case 'button': {
@@ -830,12 +832,12 @@
async function handle_methods(dmeth) {
"use strict";
//console.log('METHODS')
- for (let idmeth=0; idmeth -1) {
- if (attr == 'choices') { // menu choices are wrapped in a list
- val = m[3].slice(2,-2)
- val = val.replace(/'/g, '') // remove quotes
- let s = val.split(',')
- val = []
- for (let a of s) {val.push(a)}
+ if (attr == 'choices') { // menu choices are wrapped in a list
+ val = m[3].slice(1, -1) // remove outer brackets
+ val = val.replace(/'/g, '') // remove quotes
+ val = val.replace(/, /g, ',') // remove spaces after commas
+ let s = val.split(',')
+ val = []
+ for (let a of s) { val.push(a) }
} else {
// '\n' doesn't survive JSON transmission, so in vpython.py we replace '\n' with '
'
val = m[3].replace(/
/g, "\n")
@@ -590,8 +590,7 @@ function handler(data) {
for (var i in data[d]) console.log(i, JSON.stringify(data[d][i]))
}
*/
-
-
+
if (data.cmds !== undefined && data.cmds.length > 0) handle_cmds(data.cmds)
if (data.methods !== undefined && data.methods.length > 0) handle_methods(data.methods)
@@ -619,7 +618,7 @@ function handle_cmds(dcmds) {
var vlst = ['pos', 'color', 'size', 'axis', 'up', 'direction', 'center', 'forward', 'foreground',
'background', 'ambient', 'linecolor', 'dot_color', 'trail_color', 'textcolor', 'attrval',
'origin', 'normal', 'bumpaxis','texpos', 'start_face_color', 'end_face_color', 'marker_color',
- 'start_normal', 'end_normal', 'offset']
+ 'start_normal', 'end_normal']
if ((obj != 'gcurve') && ( obj != 'gdots' ) ) vlst.push( 'size' )
var cfg = {}
var objects = []
@@ -773,14 +772,7 @@ function handle_cmds(dcmds) {
}
break
}
- case 'local_light': {
- let g = glowObjs[idx] = local_light(cfg)
- if (cfg.offset !== undefined) { // mocking up attach_light
- g.__obj = glowObjs[cfg.attach_idx]
- g.canvas.attached_lights.push(g)
- }
- break
- }
+ case 'local_light': {glowObjs[idx] = local_light(cfg); break}
case 'distant_light': {glowObjs[idx] = distant_light(cfg); break}
case 'canvas': {
if ((typeof isjupyterlab_vpython !== 'undefined') && (isjupyterlab_vpython === true)) {
@@ -807,6 +799,19 @@ function handle_cmds(dcmds) {
// Display frames per second and render time:
//$("").appendTo(glowObjs[idx].title)
}
+ case 'attach_arrow': {
+ var attrs = ['pos', 'size', 'axis', 'up', 'color']
+ var o = glowObjs[cfg['obj']]
+ delete cfg['obj']
+ var attr = cfg['attr']
+ delete cfg['attr']
+ var val = cfg['attrval']
+ delete cfg['attrval']
+ if (attrs.indexOf(attr) < 0) attr = '_attach_arrow'
+ o.attr = val
+ glowObjs[idx] = attach_arrow( o, attr, cfg )
+ break
+ }
case 'attach_trail': {
if ( typeof cfg['_obj'] === 'string' ) {
var o = cfg['_obj'] // the string '_func'
@@ -838,13 +843,10 @@ function handle_cmds(dcmds) {
break
}
case 'radio': {
- cfg.canvas = canvas.get_selected()
- cfg = fix_location(cfg)
- delete cfg.canvas
cfg.objName = obj
cfg.bind = control_handler
+ cfg = fix_location(cfg)
glowObjs[idx] = radio(cfg)
- // glowObjs[idx].canvas = canvas.get_selected()
break
}
case 'button': {
@@ -880,12 +882,12 @@ function handle_cmds(dcmds) {
async function handle_methods(dmeth) {
"use strict";
//console.log('METHODS')
- for (let idmeth=0; idmeth