24
24
'event_return' , 'extrusion' , 'faces' , 'frame' , 'gcurve' , 'gdots' ,
25
25
'ghbars' , 'gobj' , 'graph' , 'gvbars' , 'helix' , 'label' ,
26
26
'local_light' , 'menu' , 'meta_canvas' , 'points' , 'pyramid' ,
27
- 'quad' , 'radio' , 'ring' , 'set_browser' , ' simple_sphere' , 'sleep' , 'slider' , 'sphere' ,
27
+ 'quad' , 'radio' , 'ring' , 'simple_sphere' , 'sleep' , 'slider' , 'sphere' ,
28
28
'standardAttributes' , 'text' , 'textures' , 'triangle' , 'vertex' ,
29
- 'wtext' , 'winput' ]
29
+ 'wtext' , 'winput' , 'keysdown' ]
30
30
31
31
__p = platform .python_version ()
32
32
_ispython3 = (__p [0 ] == '3' )
40
40
version = [__version__ , 'jupyter' ]
41
41
GSversion = [__gs_version__ , 'glowscript' ]
42
42
43
+ keysdownlist = [] # list of keys currently pressed
44
+
43
45
# To print immediately, do this:
44
46
# print(.....)
45
47
# sys.stdout.flush()
95
97
'right' :'q' , 'top' :'r' , 'bottom' :'s' , '_cloneid' :'t' ,
96
98
'logx' :'u' , 'logy' :'v' , 'dot' :'w' , 'dot_radius' :'x' ,
97
99
'markers' :'y' , 'legend' :'z' , 'label' :'A' , 'delta' :'B' , 'marker_color' :'C' ,
98
- 'size_units' :'D' , 'userpan' :'E' }
100
+ 'size_units' :'D' , 'userpan' :'E' , 'scroll' : 'F' }
99
101
100
102
# methods are X in {'m': '23X....'}
101
103
# pos is normally updated as an attribute, but for interval-based trails, it is updated (multiply) as a method
@@ -522,7 +524,7 @@ class standardAttributes(baseObj):
522
524
['visible' ],
523
525
[]],
524
526
'compound' :[['pos' , 'color' , 'trail_color' ],
525
- ['axis' , 'size' , 'up' ],
527
+ ['axis' , 'size' , 'up' , 'origin' ],
526
528
['visible' , 'opacity' ,'shininess' , 'emissive' ,
527
529
'make_trail' , 'trail_type' , 'interval' , 'texture' ,
528
530
'retain' , 'trail_color' , 'trail_radius' , 'obj_idxs' , 'pickable' ],
@@ -698,7 +700,7 @@ def setup(self, args):
698
700
699
701
700
702
# set canvas
701
- if self .canvas == None : ## not specified in constructor
703
+ if self .canvas is None : ## not specified in constructor
702
704
self .canvas = canvas .get_selected ()
703
705
#cmd["attrs"].append({"attr": 'canvas', "value": self.canvas.idx})
704
706
cmd ['canvas' ] = self .canvas .idx
@@ -711,7 +713,7 @@ def setup(self, args):
711
713
if _special_clone is not None : cmd ["_cloneid" ] = _special_clone
712
714
self .appendcmd (cmd )
713
715
714
- # if ('frame' in args and args['frame'] != None):
716
+ # if ('frame' in args and args['frame'] is not None):
715
717
# frame.objects.append(self)
716
718
# frame.update_obj_list()
717
719
@@ -999,9 +1001,9 @@ def rotate(self, angle=None, axis=None, origin=None):
999
1001
saveorigin = origin
1000
1002
if angle == 0 :
1001
1003
return
1002
- if angle == None :
1004
+ if angle is None :
1003
1005
raise TypeError ('You must specify an angle through which to rotate' )
1004
- if axis == None :
1006
+ if axis is None :
1005
1007
rotaxis = self .axis
1006
1008
else :
1007
1009
rotaxis = axis
@@ -1528,32 +1530,34 @@ def size(self,value): # compound axis and size don't interact
1528
1530
if not self ._constructing :
1529
1531
self .addattr ('size' )
1530
1532
1531
- def _world_zaxis (self ):
1532
- axis = self ._axis
1533
- up = norm (self ._up )
1534
- if abs (axis .dot (up )) / sqrt (axis .mag2 ) > 0.98 :
1535
- if abs (norm (axis ).dot (vector (- 1 ,0 ,0 ))) > 0.98 :
1536
- z_axis = axis .cross (vector (0 ,0 ,1 )).norm ()
1537
- else :
1538
- z_axis = axis .cross (vector (- 1 ,0 ,0 )).norm ()
1539
- else :
1540
- z_axis = axis .cross (up ).norm ()
1541
- return z_axis
1533
+ @property
1534
+ def origin (self ):
1535
+ return self ._origin
1536
+ @origin .setter
1537
+ def origin (self ,value ): # compound origin cannot be reset
1538
+ if not self ._constructing :
1539
+ raise AttributeError ('The compound "origin" attribute is read-only; change "pos" instead.' )
1540
+ self ._origin = value
1542
1541
1543
1542
def world_to_compound (self , v ):
1544
- axis = self ._axis
1545
- z_axis = self ._world_zaxis ()
1546
- y_axis = z_axis .cross (axis ).norm ()
1547
- x_axis = axis .norm ()
1548
- v = v - self ._pos
1549
- return vector (v .dot (x_axis ), v .dot (y_axis ), v .dot (z_axis ))
1543
+ v = v - self ._pos
1544
+ x_axis = self ._axis .hat
1545
+ y_axis = self ._up .hat
1546
+ z_axis = x_axis .cross (y_axis )
1547
+ ox = self ._size0 .x / self ._size .x # _size0 is the original size
1548
+ oy = self ._size0 .y / self ._size .y
1549
+ oz = self ._size0 .z / self ._size .z
1550
+ return self ._origin + vector (v .dot (x_axis )* ox , v .dot (y_axis )* oy , v .dot (z_axis )* oz )
1550
1551
1551
1552
def compound_to_world (self , v ):
1552
- axis = self ._axis
1553
- z_axis = self ._world_zaxis ()
1554
- y_axis = z_axis .cross (axis ).norm ()
1555
- x_axis = axis .norm ()
1556
- return self ._pos + (v .x * x_axis ) + (v .y * y_axis ) + (v .z * z_axis )
1553
+ v = v - self ._origin
1554
+ x_axis = self ._axis .hat
1555
+ y_axis = self ._up .hat
1556
+ z_axis = x_axis .cross (y_axis )
1557
+ ox = self ._size .x / self ._size0 .x # _size0 is the original size
1558
+ oy = self ._size .y / self ._size0 .y
1559
+ oz = self ._size .z / self ._size0 .z
1560
+ return self ._pos + v .x * ox * x_axis + v .y * oy * y_axis + v .z * oz * z_axis
1557
1561
1558
1562
class vertex (standardAttributes ):
1559
1563
def __init__ (self , ** args ):
@@ -1961,7 +1965,7 @@ def __init__(self,*args1, **args):
1961
1965
1962
1966
super (curveMethods , self ).setup (args )
1963
1967
1964
- if tpos != None :
1968
+ if tpos is not None :
1965
1969
if len (args1 ) > 0 : raise AttributeError ('Malformed constructor' )
1966
1970
self .append (tpos )
1967
1971
if len (args1 ) > 0 :
@@ -1985,7 +1989,7 @@ def __init__(self,*args1, **args):
1985
1989
1986
1990
super (curveMethods , self ).setup (args )
1987
1991
1988
- if tpos != None :
1992
+ if tpos is not None :
1989
1993
if len (args1 ) > 0 : raise AttributeError ('Malformed constructor' )
1990
1994
self .append (tpos )
1991
1995
if len (args1 ) > 0 :
@@ -2278,6 +2282,7 @@ def __init__(self, **args):
2278
2282
self ._title = ""
2279
2283
self ._xtitle = ""
2280
2284
self ._ytitle = ""
2285
+ self ._scroll = False
2281
2286
argsToSend = []
2282
2287
2283
2288
## override default vector attributes
@@ -2292,7 +2297,7 @@ def __init__(self, **args):
2292
2297
2293
2298
## override default scalar attributes
2294
2299
scalarAttributes = ['width' , 'height' , 'title' , 'xtitle' , 'ytitle' ,'align' ,
2295
- 'xmin' , 'xmax' , 'ymin' , 'ymax' , 'logx' , 'logy' , 'fast' ]
2300
+ 'xmin' , 'xmax' , 'ymin' , 'ymax' , 'logx' , 'logy' , 'fast' , 'scroll' ]
2296
2301
for a in scalarAttributes :
2297
2302
if a in args :
2298
2303
argsToSend .append (a )
@@ -2305,6 +2310,12 @@ def __init__(self, **args):
2305
2310
2306
2311
cmd = {"cmd" : objName , "idx" : self .idx }
2307
2312
2313
+ if self ._scroll :
2314
+ if not ('xmin' in argsToSend and 'xmax' in argsToSend ):
2315
+ raise AttributeError ("For a scrolling graph, both xmin and xmax must be specified." )
2316
+ if self ._xmax <= self ._xmin :
2317
+ raise AttributeError ("For a scrolling graph, xmax must be greater than xmin." )
2318
+
2308
2319
## send only args specified in constructor
2309
2320
for a in argsToSend :
2310
2321
aval = getattr (self ,a )
@@ -2318,11 +2329,16 @@ def __init__(self, **args):
2318
2329
def fast (self ): return self ._fast
2319
2330
@fast .setter
2320
2331
def fast (self ,val ):
2321
- # if _isnotebook and not val:
2322
- # raise AttributeError('"fast = False" is currently not available in a Jupyter notebook.')
2323
2332
self ._fast = val
2324
2333
self .addattr ('fast' )
2325
2334
2335
+ @property
2336
+ def scroll (self ): return self ._scroll
2337
+ @scroll .setter
2338
+ def scroll (self ,val ):
2339
+ self ._scroll = val
2340
+ self .addattr ('scroll' )
2341
+
2326
2342
@property
2327
2343
def width (self ): return self ._width
2328
2344
@width .setter
@@ -2814,7 +2830,7 @@ def __init__(self, **args):
2814
2830
2815
2831
for a in canvasNonVecAttrs :
2816
2832
if a in args :
2817
- if args [a ] != None :
2833
+ if args [a ] is not None :
2818
2834
setattr (self , '_' + a , args [a ])
2819
2835
cmd [a ]= args [a ]
2820
2836
del args [a ]
@@ -3099,11 +3115,13 @@ def objz(self, obj, operation):
3099
3115
3100
3116
## key events conflict with notebook command mode; not permitted for now
3101
3117
def handle_event (self , evt ): ## events and scene info updates
3118
+ global keysdownlist
3102
3119
ev = evt ['event' ]
3103
3120
if ev == 'pick' :
3104
3121
self .mouse .setpick ( evt )
3105
3122
self ._waitfor = True # what pick is looking for
3106
3123
elif ev == '_compound' : # compound, text, extrusion
3124
+ print ('compound event return' )
3107
3125
obj = self ._compound
3108
3126
p = evt ['pos' ]
3109
3127
if obj ._objName == 'text' :
@@ -3115,7 +3133,7 @@ def handle_event(self, evt): ## events and scene info updates
3115
3133
# on_change functions that detect changes in e.g. obj.pos.y
3116
3134
obj ._pos .value = list_to_vec (p )
3117
3135
s = evt ['size' ]
3118
- obj ._size .value = list_to_vec (s )
3136
+ obj ._size .value = obj . _size0 = list_to_vec (s )
3119
3137
obj ._axis .value = obj ._size ._x * norm (obj ._axis )
3120
3138
obj ._up .value = list_to_vec (evt ['up' ])
3121
3139
self ._waitfor = True # what compound and text and extrusion are looking for in _wait()
@@ -3182,6 +3200,8 @@ def handle_event(self, evt): ## events and scene info updates
3182
3200
if 'autoscale' in evt and self .userzoom and not self ._set_autoscale :
3183
3201
self ._autoscale = evt ['autoscale' ]
3184
3202
self ._set_autoscale = False
3203
+ if 'keysdown' in evt : keysdownlist = evt ['keysdown' ]
3204
+
3185
3205
3186
3206
def bind (self , eventtype , whattodo ):
3187
3207
evts = eventtype .split ()
@@ -3255,7 +3275,7 @@ def __init__(self, **args):
3255
3275
args ['_objName' ] = "local_light"
3256
3276
super (local_light , self ).setup (args )
3257
3277
3258
- if (canvas .get_selected () != None ):
3278
+ if (canvas .get_selected () is not None ):
3259
3279
canvas .get_selected ()._lights .append (self )
3260
3280
3261
3281
class distant_light (standardAttributes ):
@@ -3265,7 +3285,7 @@ def __init__(self, **args):
3265
3285
self ._direction = vector (0 ,0 ,1 )
3266
3286
super (distant_light , self ).setup (args )
3267
3287
3268
- if (canvas .get_selected () != None ):
3288
+ if (canvas .get_selected () is not None ):
3269
3289
canvas .get_selected ()._lights .append (self )
3270
3290
3271
3291
@property
@@ -4092,11 +4112,9 @@ def print_to_string(*args): # treatment of <br> vs. \n not quite right here
4092
4112
s = s [:- 1 ]
4093
4113
return (s )
4094
4114
4095
- # global variable for type of web browser to display vpython
4096
- _browsertype = 'default'
4097
- def set_browser (type = 'default' ):
4098
- global _browsertype
4099
- if type == 'pyqt' :
4100
- _browsertype = 'pyqt'
4101
- else :
4102
- _browsertype = 'default'
4115
+ def keysdown ():
4116
+ global keysdownlist
4117
+ keys = []
4118
+ for k in keysdownlist : # return a copy of keysdownlist
4119
+ keys .append (k )
4120
+ return keys
0 commit comments