Skip to content

Commit d3341b4

Browse files
committed
Ensure no trait/widget collisions
1 parent 8be79e3 commit d3341b4

File tree

4 files changed

+143
-119
lines changed

4 files changed

+143
-119
lines changed

js/scripts/generate-wrappers.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,17 @@ const IGNORE_FILES = [
5151
'**/animation/KeyframeTrackConstructor.js', // Sub-part of one object, ignore
5252
'**/animation/KeyframeTrackPrototype.js', // Sub-part of one object, ignore
5353
'**/audio/AudioContext.js', // JS API for audio, nothing to expose
54+
'**/core/Face3.js', // Implemented as trait only, not widget model
5455
'**/geometries/Geometries.js', // index.js like file, nothing new here
5556
'**/materials/Materials.js', // index.js like file, nothing new here
5657
'**/materials/MeshDistanceMaterial.js', // TODO: Undocumented as of yet
58+
'**/math/Vector2.js', // Implemented as trait only, not widget model
59+
'**/math/Vector3.js', // Implemented as trait only, not widget model
60+
'**/math/Vector4.js', // Implemented as trait only, not widget model
61+
'**/math/Matrix3.js', // Implemented as trait only, not widget model
62+
'**/math/Matrix4.js', // Implemented as trait only, not widget model
63+
'**/math/Color.js', // Implemented as trait only, not widget model
64+
'**/math/Euler.js', // Implemented as trait only, not widget model
5765
'**/renderers/WebGLRenderer.js', // For now, the internals of the webgl
5866
'**/renderers/WebGL2Renderer.js', // render is not exposed.
5967
//'**/renderers/webgl/**',

js/scripts/prop-types.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ class Vector2 extends BaseType {
411411
this.defaultValue = [ x||0, y||0 ];
412412
}
413413
getTraitlet() {
414-
return 'Vector2(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
414+
return 'Vector2(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
415415
}
416416
getPropertyConverterFn() {
417417
return 'convertVector';
@@ -427,7 +427,7 @@ class Vector3 extends BaseType {
427427
this.defaultValue = [ x||0, y||0, z||0 ];
428428
}
429429
getTraitlet() {
430-
return 'Vector3(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
430+
return 'Vector3(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
431431
}
432432
getPropertyConverterFn() {
433433
return 'convertVector';
@@ -443,7 +443,7 @@ class Vector4 extends BaseType {
443443
this.defaultValue = [ x||0, y||0, z||0, w||0 ];
444444
}
445445
getTraitlet() {
446-
return 'Vector4(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
446+
return 'Vector4(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
447447
}
448448
getPropertyConverterFn() {
449449
return 'convertVector';
@@ -495,7 +495,7 @@ class Matrix3 extends BaseType {
495495
];
496496
}
497497
getTraitlet() {
498-
return 'Matrix3(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
498+
return 'Matrix3(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
499499
}
500500
getPropertyConverterFn() {
501501
return 'convertMatrix';
@@ -516,7 +516,7 @@ class Matrix4 extends BaseType {
516516
];
517517
}
518518
getTraitlet() {
519-
return 'Matrix4(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
519+
return 'Matrix4(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
520520
}
521521
getPropertyConverterFn() {
522522
return 'convertMatrix';
@@ -534,7 +534,7 @@ class Euler extends BaseType {
534534
}
535535

536536
getTraitlet() {
537-
return 'Euler(default=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
537+
return 'Euler(default_value=' + JSON.stringify(this.defaultValue) + ').tag(sync=True)';
538538
}
539539
getPropertyConverterFn() {
540540
return 'convertEuler';

js/scripts/three-class-config.js

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -302,21 +302,6 @@ module.exports = {
302302
EventDispatcher: {
303303
relativePath: './core/EventDispatcher',
304304
},
305-
Face3: {
306-
relativePath: './core/Face3',
307-
properties: {
308-
a: new Types.Int(0),
309-
b: new Types.Int(1),
310-
c: new Types.Int(2),
311-
normal: new Types.Vector3(),
312-
color: new Types.Color('#ffffff'),
313-
// TODO: arrays of vectors/colors
314-
// vertexNormals: new Types.ThreeTypeArray('Vector3')
315-
// vertexColors: new Types.ThreeTypeArray('Color')
316-
materialIndex: new Types.Int(0),
317-
},
318-
constructorArgs: [ 'a', 'b', 'c', 'normal', 'color', 'materialIndex' ],
319-
},
320305
BaseGeometry: {
321306
relativePath: './core/BaseGeometry',
322307
properties: {
@@ -925,15 +910,6 @@ module.exports = {
925910
constructorArgs: [ 'min', 'max' ],
926911

927912
},
928-
Color: {
929-
relativePath: './math/Color',
930-
properties: {
931-
r: new Types.Float(1.0),
932-
g: new Types.Float(1.0),
933-
b: new Types.Float(1.0),
934-
},
935-
constructorArgs: [ 'r', 'g', 'b' ],
936-
},
937913
Cylindrical: {
938914
relativePath: './math/Cylindrical',
939915
properties: {
@@ -943,16 +919,6 @@ module.exports = {
943919
},
944920
constructorArgs: ['radius', 'theta', 'y'],
945921
},
946-
Euler: {
947-
relativePath: './math/Euler',
948-
properties: {
949-
x: new Types.Float(0),
950-
y: new Types.Float(0),
951-
z: new Types.Float(0),
952-
order: new Types.String('XYZ'),
953-
},
954-
constructorArgs: [ 'x', 'y', 'z', 'order' ],
955-
},
956922
Frustum: {
957923
relativePath: './math/Frustum',
958924
properties: {
@@ -979,18 +945,6 @@ module.exports = {
979945
Math: {
980946
relativePath: './math/Math',
981947
},
982-
Matrix3: {
983-
relativePath: './math/Matrix3',
984-
properties: {
985-
elements: new Types.Array(),
986-
},
987-
},
988-
Matrix4: {
989-
relativePath: './math/Matrix4',
990-
properties: {
991-
elements: new Types.Array(),
992-
},
993-
},
994948
Plane: {
995949
relativePath: './math/Plane',
996950
properties: {
@@ -1044,33 +998,6 @@ module.exports = {
1044998
},
1045999
constructorArgs: [ 'a', 'b', 'c' ],
10461000
},
1047-
Vector2: {
1048-
relativePath: './math/Vector2',
1049-
properties: {
1050-
x: new Types.Float(),
1051-
y: new Types.Float(),
1052-
},
1053-
constructorArgs: [ 'x', 'y' ],
1054-
},
1055-
Vector3: {
1056-
relativePath: './math/Vector3',
1057-
properties: {
1058-
x: new Types.Float(),
1059-
y: new Types.Float(),
1060-
z: new Types.Float(),
1061-
},
1062-
constructorArgs: [ 'x', 'y', 'z' ],
1063-
},
1064-
Vector4: {
1065-
relativePath: './math/Vector4',
1066-
properties: {
1067-
x: new Types.Float(),
1068-
y: new Types.Float(),
1069-
z: new Types.Float(),
1070-
w: new Types.Float(),
1071-
},
1072-
constructorArgs: [ 'x', 'y', 'z', 'w' ],
1073-
},
10741001
Bone: {
10751002
relativePath: './objects/Bone',
10761003
superClass: 'Object3D',

pythreejs/traits.py

Lines changed: 129 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,158 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4+
from collections import namedtuple, Sequence
5+
46
from traitlets import (
57
Unicode, Int, CInt, Instance, Enum, List, Dict, Float, CFloat,
6-
Bool, Tuple, Undefined, TraitError, Union,
8+
Bool, Tuple, Undefined, TraitError, Union, TraitType
79
)
810

911
from ipywidgets import widget_serialization
1012

1113
from ipydatawidgets import DataUnion, NDArrayWidget
1214

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)
1715

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'
2259

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)
2764

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 = (
3171
1, 0, 0,
3272
0, 1, 0,
3373
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)
3681

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 = (
4088
1, 0, 0, 0,
4189
0, 1, 0, 0,
4290
0, 0, 1, 0,
4391
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)
59127
)
60128

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)
65149

66150

67151
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+
"""
68156
def validate(self, obj, value):
69157
value = super(WebGLDataUnion, self).validate(obj, value)
70158
array = value.array if isinstance(value, NDArrayWidget) else value
@@ -79,6 +167,7 @@ def validate(self, obj, value):
79167

80168

81169
class Uninitialized:
170+
"""Placeholder sentinel used while waiting for a initialization via sync"""
82171
pass
83172

84173
_widget_to_json = widget_serialization['to_json']

0 commit comments

Comments
 (0)