1
1
#!/usr/bin/env python
2
2
# -*- coding: utf-8 -*-
3
3
4
+ from collections import namedtuple , Sequence
5
+
4
6
from traitlets import (
5
7
Unicode , Int , CInt , Instance , Enum , List , Dict , Float , CFloat ,
6
- Bool , Tuple , Undefined , TraitError , Union ,
8
+ Bool , Tuple , Undefined , TraitError , Union , TraitType
7
9
)
8
10
9
11
from ipywidgets import widget_serialization
10
12
11
13
from ipydatawidgets import DataUnion , NDArrayWidget
12
14
13
- def Vector2 (trait_type = CFloat , default = None , ** kwargs ):
14
- if default is None :
15
- default = [0 , 0 ]
16
- return List (trait_type , default_value = default , minlen = 2 , maxlen = 2 , ** kwargs )
17
15
18
- def Vector3 (trait_type = CFloat , default = None , ** kwargs ):
19
- if default is None :
20
- default = [0 , 0 , 0 ]
21
- return List (trait_type , default_value = default , minlen = 3 , maxlen = 3 , ** kwargs )
16
+ def _castable_namedtuple (typename , field_names ):
17
+ base = namedtuple ('%s_base' % typename , field_names )
18
+
19
+ def new_new (cls , * args , ** kwargs ):
20
+ if not kwargs and len (args ) == 1 and isinstance (args , Sequence ):
21
+ return base .__new__ (cls , * args [0 ], ** kwargs )
22
+ return base .__new__ (cls , * args , ** kwargs )
23
+
24
+ return type (typename , (base ,), {'__new__' : new_new })
25
+
26
+
27
+ class Vector2 (Tuple ):
28
+ """A trait for a 2-tuple corresponding to a three.js Vector2.
29
+ """
30
+
31
+ default_value = (0 , 0 )
32
+ info_text = 'a two-element vector'
33
+
34
+ def __init__ (self , trait = CFloat , default_value = Undefined , ** kwargs ):
35
+ if default_value is Undefined :
36
+ default_value = self .default_value
37
+ super (Vector2 , self ).__init__ (* (trait , trait ), default_value = default_value , ** kwargs )
38
+
39
+
40
+ class Vector3 (Tuple ):
41
+ """A trait for a 3-tuple corresponding to a three.js Vector3.
42
+ """
43
+
44
+ default_value = (0 , 0 , 0 )
45
+ info_text = 'a three-element vector'
46
+
47
+ def __init__ (self , trait = CFloat , default_value = Undefined , ** kwargs ):
48
+ if default_value is Undefined :
49
+ default_value = self .default_value
50
+ super (Vector3 , self ).__init__ (* (trait , trait , trait ), default_value = default_value , ** kwargs )
51
+
52
+
53
+ class Vector4 (Tuple ):
54
+ """A trait for a 4-tuple corresponding to a three.js Vector4.
55
+ """
56
+
57
+ default_value = (0 , 0 , 0 , 0 )
58
+ info_text = 'a four-element vector'
22
59
23
- def Vector4 ( trait_type = CFloat , default = None , ** kwargs ):
24
- if default is None :
25
- default = [ 0 , 0 , 0 , 0 ]
26
- return List ( trait_type , default_value = default , minlen = 4 , maxlen = 4 , ** kwargs )
60
+ def __init__ ( self , trait = CFloat , default_value = Undefined , ** kwargs ):
61
+ if default_value is Undefined :
62
+ default_value = self . default_value
63
+ super ( Vector4 , self ). __init__ ( * ( trait , trait , trait , trait ), default_value = default_value , ** kwargs )
27
64
28
- def Matrix3 (trait_type = CFloat , default = None , ** kwargs ):
29
- if default is None :
30
- default = [
65
+
66
+ class Matrix3 (Tuple ):
67
+ """A trait for a 9-tuple corresponding to a three.js Matrix3.
68
+ """
69
+
70
+ default_value = (
31
71
1 , 0 , 0 ,
32
72
0 , 1 , 0 ,
33
73
0 , 0 , 1
34
- ]
35
- return List (trait_type , default_value = default , minlen = 9 , maxlen = 9 , ** kwargs )
74
+ )
75
+ info_text = 'a three-by-three matrix (9 element tuple)'
76
+
77
+ def __init__ (self , trait = CFloat , default_value = Undefined , ** kwargs ):
78
+ if default_value is Undefined :
79
+ default_value = self .default_value
80
+ super (Matrix3 , self ).__init__ (* ((trait ,) * 9 ), default_value = default_value , ** kwargs )
36
81
37
- def Matrix4 (trait_type = CFloat , default = None , ** kwargs ):
38
- if default is None :
39
- default = [
82
+
83
+ class Matrix4 (Tuple ):
84
+ """A trait for a 16-tuple corresponding to a three.js Matrix4.
85
+ """
86
+
87
+ default_value = (
40
88
1 , 0 , 0 , 0 ,
41
89
0 , 1 , 0 , 0 ,
42
90
0 , 0 , 1 , 0 ,
43
91
0 , 0 , 0 , 1
44
- ]
45
- return List (trait_type , default_value = default , minlen = 16 , maxlen = 16 , ** kwargs )
46
-
47
- def Face3 (** kwargs ):
48
- return Tuple (
49
- CInt (), # a - Vertex A index.
50
- CInt (), # b - Vertex B index.
51
- CInt (), # c - Vertex C index.
52
- Union ([ # normal - (optional) Face normal (Vector3) or array of 3 vertex normals.
53
- Vector3 (),
54
- List (Vector3 (), minlen = 3 , maxlen = 3 )]),
55
- Union ([ # color - (optional) Face color or array of vertex colors.
56
- Unicode (),
57
- List (Unicode (), minlen = 3 , maxlen = 3 )]),
58
- CInt (), # materialIndex - (optional) which index of an array of materials to associate with the face.
92
+ )
93
+ info_text = 'a four-by-four matrix (16 element tuple)'
94
+
95
+ def __init__ (self , trait = CFloat , default_value = Undefined , ** kwargs ):
96
+ if default_value is Undefined :
97
+ default_value = self .default_value
98
+ super (Matrix4 , self ).__init__ (* ((trait ,) * 16 ), default_value = default_value , ** kwargs )
99
+
100
+
101
+ class Face3 (Tuple ):
102
+ """A trait for a named tuple corresponding to a three.js Face3.
103
+
104
+ Accepts named tuples with the field names:
105
+ ('a', 'b', 'c', 'normal', 'color', 'materialIndex')
106
+ """
107
+ klass = _castable_namedtuple ('Face3' , ('a' , 'b' , 'c' , 'normal' , 'color' , 'materialIndex' ))
108
+ _cast_types = (list , tuple )
109
+
110
+ info_text = 'a named tuple representing a Face3'
111
+
112
+ def __init__ (self , ** kwargs ):
113
+ super (Face3 , self ).__init__ (
114
+ CInt (), # a - Vertex A index.
115
+ CInt (), # b - Vertex B index.
116
+ CInt (), # c - Vertex C index.
117
+ Union ([ # normal - (optional) Face normal (Vector3) or array of 3 vertex normals.
118
+ Vector3 (allow_none = True ),
119
+ Tuple ((Vector3 (),) * 3 ),
120
+ ]),
121
+ Union ([ # color - (optional) Face color or array of vertex colors.
122
+ Unicode (allow_none = True ),
123
+ Tuple ((Unicode (),) * 3 ),
124
+ ]),
125
+ CInt (allow_none = True ), # materialIndex - (optional) which index of an array of materials to associate with the face.
126
+ default_value = (0 , 0 , 0 , None , None , None )
59
127
)
60
128
61
- def Euler (default = None , ** kwargs ):
62
- if default is None :
63
- default = [0 , 0 , 0 , 'XYZ' ]
64
- return Tuple (CFloat (), CFloat (), CFloat (), Unicode (), default_value = default , ** kwargs )
129
+
130
+ class Euler (Tuple ):
131
+ """A trait for a set of Euler angles.
132
+
133
+ Expressed as a tuple of tree floats (the angles), and the order as a string.
134
+ See the three.js docs for futher details.
135
+ """
136
+
137
+ info_text = 'a set of Euler angles'
138
+ default_value = (0 , 0 , 0 , 'XYZ' )
139
+
140
+ _accepted_orders = ['XYZ' , 'YZX' , 'ZXY' , 'XZY' , 'YXZ' , 'ZYX' ]
141
+
142
+ def __init__ (self , default_value = Undefined , ** kwargs ):
143
+ if default_value is Undefined :
144
+ default_value = self .default_value
145
+ super (Euler , self ).__init__ (
146
+ CFloat (), CFloat (), CFloat (),
147
+ Enum (self ._accepted_orders , self ._accepted_orders [0 ]),
148
+ default_value = default_value , ** kwargs )
65
149
66
150
67
151
class WebGLDataUnion (DataUnion ):
152
+ """A trait that accepts either a numpy array, or an NDArrayWidget reference.
153
+
154
+ Also constrains the use of 64-bit arrays, as this is not supported by WebGL.
155
+ """
68
156
def validate (self , obj , value ):
69
157
value = super (WebGLDataUnion , self ).validate (obj , value )
70
158
array = value .array if isinstance (value , NDArrayWidget ) else value
@@ -79,6 +167,7 @@ def validate(self, obj, value):
79
167
80
168
81
169
class Uninitialized :
170
+ """Placeholder sentinel used while waiting for a initialization via sync"""
82
171
pass
83
172
84
173
_widget_to_json = widget_serialization ['to_json' ]
0 commit comments