anythreejs 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- anythreejs/__init__.py +153 -0
- anythreejs/core/__init__.py +109 -0
- anythreejs/core/base.py +210 -0
- anythreejs/core/buffer.py +89 -0
- anythreejs/core/camera.py +193 -0
- anythreejs/core/controls.py +131 -0
- anythreejs/core/geometry.py +317 -0
- anythreejs/core/helpers.py +63 -0
- anythreejs/core/lights.py +242 -0
- anythreejs/core/material.py +437 -0
- anythreejs/core/objects.py +200 -0
- anythreejs/core/scene.py +36 -0
- anythreejs/core/textures.py +46 -0
- anythreejs/py.typed +0 -0
- anythreejs/renderer.py +156 -0
- anythreejs/widget.css +11 -0
- anythreejs/widget.js +871 -0
- anythreejs-0.0.1.dist-info/METADATA +169 -0
- anythreejs-0.0.1.dist-info/RECORD +21 -0
- anythreejs-0.0.1.dist-info/WHEEL +4 -0
- anythreejs-0.0.1.dist-info/licenses/LICENSE +29 -0
anythreejs/__init__.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""
|
|
2
|
+
anythreejs - A modern Python/Three.js bridge for Jupyter
|
|
3
|
+
|
|
4
|
+
Quick start:
|
|
5
|
+
from anythreejs import Renderer, Scene, PerspectiveCamera, OrbitControls
|
|
6
|
+
from anythreejs import Mesh, BoxGeometry, MeshStandardMaterial, AmbientLight
|
|
7
|
+
|
|
8
|
+
scene = Scene(background="#1a1a2e")
|
|
9
|
+
scene.add(Mesh(BoxGeometry(1, 1, 1), MeshStandardMaterial(color="#ff6600")))
|
|
10
|
+
scene.add(AmbientLight(intensity=0.5))
|
|
11
|
+
|
|
12
|
+
camera = PerspectiveCamera(position=(0, 0, 5))
|
|
13
|
+
controls = OrbitControls(controlling=camera)
|
|
14
|
+
|
|
15
|
+
renderer = Renderer(camera=camera, scene=scene, controls=[controls])
|
|
16
|
+
renderer # Display in notebook
|
|
17
|
+
|
|
18
|
+
For pythreejs-style namespace imports:
|
|
19
|
+
import anythreejs as p3
|
|
20
|
+
# Then use p3.Scene, p3.Renderer, etc.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .renderer import Renderer
|
|
24
|
+
from .core import (
|
|
25
|
+
# Base
|
|
26
|
+
ThreeJSBase,
|
|
27
|
+
Object3D,
|
|
28
|
+
# Scene
|
|
29
|
+
Scene,
|
|
30
|
+
# Cameras
|
|
31
|
+
PerspectiveCamera,
|
|
32
|
+
OrthographicCamera,
|
|
33
|
+
# Controls
|
|
34
|
+
OrbitControls,
|
|
35
|
+
TrackballControls,
|
|
36
|
+
# Geometry
|
|
37
|
+
BufferGeometry,
|
|
38
|
+
BoxGeometry,
|
|
39
|
+
BoxBufferGeometry,
|
|
40
|
+
SphereGeometry,
|
|
41
|
+
SphereBufferGeometry,
|
|
42
|
+
PlaneGeometry,
|
|
43
|
+
PlaneBufferGeometry,
|
|
44
|
+
CylinderGeometry,
|
|
45
|
+
CylinderBufferGeometry,
|
|
46
|
+
TorusGeometry,
|
|
47
|
+
EdgesGeometry,
|
|
48
|
+
# Material
|
|
49
|
+
Material,
|
|
50
|
+
MeshBasicMaterial,
|
|
51
|
+
MeshStandardMaterial,
|
|
52
|
+
MeshPhongMaterial,
|
|
53
|
+
MeshLambertMaterial,
|
|
54
|
+
PointsMaterial,
|
|
55
|
+
LineBasicMaterial,
|
|
56
|
+
LineDashedMaterial,
|
|
57
|
+
SpriteMaterial,
|
|
58
|
+
# Objects
|
|
59
|
+
Mesh,
|
|
60
|
+
Points,
|
|
61
|
+
Line,
|
|
62
|
+
LineSegments,
|
|
63
|
+
Group,
|
|
64
|
+
Sprite,
|
|
65
|
+
# Lights
|
|
66
|
+
AmbientLight,
|
|
67
|
+
DirectionalLight,
|
|
68
|
+
PointLight,
|
|
69
|
+
HemisphereLight,
|
|
70
|
+
SpotLight,
|
|
71
|
+
# Helpers
|
|
72
|
+
AxesHelper,
|
|
73
|
+
GridHelper,
|
|
74
|
+
# Buffer
|
|
75
|
+
BufferAttribute,
|
|
76
|
+
Float32BufferAttribute,
|
|
77
|
+
Uint32BufferAttribute,
|
|
78
|
+
Uint16BufferAttribute,
|
|
79
|
+
Int32BufferAttribute,
|
|
80
|
+
# Textures
|
|
81
|
+
TextTexture,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Convenience alias for pythreejs-style imports: `import anythreejs as p3`
|
|
85
|
+
import sys as _sys
|
|
86
|
+
|
|
87
|
+
p3 = _sys.modules[__name__]
|
|
88
|
+
|
|
89
|
+
__version__ = "0.0.1"
|
|
90
|
+
|
|
91
|
+
__all__ = [
|
|
92
|
+
# Renderer
|
|
93
|
+
"Renderer",
|
|
94
|
+
# Base
|
|
95
|
+
"ThreeJSBase",
|
|
96
|
+
"Object3D",
|
|
97
|
+
# Scene
|
|
98
|
+
"Scene",
|
|
99
|
+
# Cameras
|
|
100
|
+
"PerspectiveCamera",
|
|
101
|
+
"OrthographicCamera",
|
|
102
|
+
# Controls
|
|
103
|
+
"OrbitControls",
|
|
104
|
+
"TrackballControls",
|
|
105
|
+
# Geometry
|
|
106
|
+
"BufferGeometry",
|
|
107
|
+
"BoxGeometry",
|
|
108
|
+
"BoxBufferGeometry",
|
|
109
|
+
"SphereGeometry",
|
|
110
|
+
"SphereBufferGeometry",
|
|
111
|
+
"PlaneGeometry",
|
|
112
|
+
"PlaneBufferGeometry",
|
|
113
|
+
"CylinderGeometry",
|
|
114
|
+
"CylinderBufferGeometry",
|
|
115
|
+
"TorusGeometry",
|
|
116
|
+
"EdgesGeometry",
|
|
117
|
+
# Material
|
|
118
|
+
"Material",
|
|
119
|
+
"MeshBasicMaterial",
|
|
120
|
+
"MeshStandardMaterial",
|
|
121
|
+
"MeshPhongMaterial",
|
|
122
|
+
"MeshLambertMaterial",
|
|
123
|
+
"PointsMaterial",
|
|
124
|
+
"LineBasicMaterial",
|
|
125
|
+
"LineDashedMaterial",
|
|
126
|
+
"SpriteMaterial",
|
|
127
|
+
# Objects
|
|
128
|
+
"Mesh",
|
|
129
|
+
"Points",
|
|
130
|
+
"Line",
|
|
131
|
+
"LineSegments",
|
|
132
|
+
"Group",
|
|
133
|
+
"Sprite",
|
|
134
|
+
# Lights
|
|
135
|
+
"AmbientLight",
|
|
136
|
+
"DirectionalLight",
|
|
137
|
+
"PointLight",
|
|
138
|
+
"HemisphereLight",
|
|
139
|
+
"SpotLight",
|
|
140
|
+
# Helpers
|
|
141
|
+
"AxesHelper",
|
|
142
|
+
"GridHelper",
|
|
143
|
+
# Buffer
|
|
144
|
+
"BufferAttribute",
|
|
145
|
+
"Float32BufferAttribute",
|
|
146
|
+
"Uint32BufferAttribute",
|
|
147
|
+
"Uint16BufferAttribute",
|
|
148
|
+
"Int32BufferAttribute",
|
|
149
|
+
# Textures
|
|
150
|
+
"TextTexture",
|
|
151
|
+
# Convenience alias
|
|
152
|
+
"p3",
|
|
153
|
+
]
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core Three.js components.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .base import ThreeJSBase, Object3D
|
|
6
|
+
from .scene import Scene
|
|
7
|
+
from .camera import PerspectiveCamera, OrthographicCamera
|
|
8
|
+
from .controls import OrbitControls, TrackballControls
|
|
9
|
+
from .geometry import (
|
|
10
|
+
BufferGeometry,
|
|
11
|
+
BoxGeometry,
|
|
12
|
+
BoxBufferGeometry,
|
|
13
|
+
SphereGeometry,
|
|
14
|
+
SphereBufferGeometry,
|
|
15
|
+
PlaneGeometry,
|
|
16
|
+
PlaneBufferGeometry,
|
|
17
|
+
CylinderGeometry,
|
|
18
|
+
CylinderBufferGeometry,
|
|
19
|
+
TorusGeometry,
|
|
20
|
+
EdgesGeometry,
|
|
21
|
+
)
|
|
22
|
+
from .material import (
|
|
23
|
+
Material,
|
|
24
|
+
MeshBasicMaterial,
|
|
25
|
+
MeshStandardMaterial,
|
|
26
|
+
MeshPhongMaterial,
|
|
27
|
+
MeshLambertMaterial,
|
|
28
|
+
PointsMaterial,
|
|
29
|
+
LineBasicMaterial,
|
|
30
|
+
LineDashedMaterial,
|
|
31
|
+
SpriteMaterial,
|
|
32
|
+
)
|
|
33
|
+
from .objects import Mesh, Points, Line, LineSegments, Group, Sprite
|
|
34
|
+
from .lights import (
|
|
35
|
+
AmbientLight,
|
|
36
|
+
DirectionalLight,
|
|
37
|
+
PointLight,
|
|
38
|
+
HemisphereLight,
|
|
39
|
+
SpotLight,
|
|
40
|
+
)
|
|
41
|
+
from .helpers import AxesHelper, GridHelper
|
|
42
|
+
from .buffer import (
|
|
43
|
+
BufferAttribute,
|
|
44
|
+
Float32BufferAttribute,
|
|
45
|
+
Uint32BufferAttribute,
|
|
46
|
+
Uint16BufferAttribute,
|
|
47
|
+
Int32BufferAttribute,
|
|
48
|
+
)
|
|
49
|
+
from .textures import TextTexture
|
|
50
|
+
|
|
51
|
+
__all__ = [
|
|
52
|
+
# Base
|
|
53
|
+
"ThreeJSBase",
|
|
54
|
+
"Object3D",
|
|
55
|
+
# Scene
|
|
56
|
+
"Scene",
|
|
57
|
+
# Cameras
|
|
58
|
+
"PerspectiveCamera",
|
|
59
|
+
"OrthographicCamera",
|
|
60
|
+
# Controls
|
|
61
|
+
"OrbitControls",
|
|
62
|
+
"TrackballControls",
|
|
63
|
+
# Geometry
|
|
64
|
+
"BufferGeometry",
|
|
65
|
+
"BoxGeometry",
|
|
66
|
+
"BoxBufferGeometry",
|
|
67
|
+
"SphereGeometry",
|
|
68
|
+
"SphereBufferGeometry",
|
|
69
|
+
"PlaneGeometry",
|
|
70
|
+
"PlaneBufferGeometry",
|
|
71
|
+
"CylinderGeometry",
|
|
72
|
+
"CylinderBufferGeometry",
|
|
73
|
+
"TorusGeometry",
|
|
74
|
+
"EdgesGeometry",
|
|
75
|
+
# Material
|
|
76
|
+
"Material",
|
|
77
|
+
"MeshBasicMaterial",
|
|
78
|
+
"MeshStandardMaterial",
|
|
79
|
+
"MeshPhongMaterial",
|
|
80
|
+
"MeshLambertMaterial",
|
|
81
|
+
"PointsMaterial",
|
|
82
|
+
"LineBasicMaterial",
|
|
83
|
+
"LineDashedMaterial",
|
|
84
|
+
"SpriteMaterial",
|
|
85
|
+
# Objects
|
|
86
|
+
"Mesh",
|
|
87
|
+
"Points",
|
|
88
|
+
"Line",
|
|
89
|
+
"LineSegments",
|
|
90
|
+
"Group",
|
|
91
|
+
"Sprite",
|
|
92
|
+
# Lights
|
|
93
|
+
"AmbientLight",
|
|
94
|
+
"DirectionalLight",
|
|
95
|
+
"PointLight",
|
|
96
|
+
"HemisphereLight",
|
|
97
|
+
"SpotLight",
|
|
98
|
+
# Helpers
|
|
99
|
+
"AxesHelper",
|
|
100
|
+
"GridHelper",
|
|
101
|
+
# Buffer
|
|
102
|
+
"BufferAttribute",
|
|
103
|
+
"Float32BufferAttribute",
|
|
104
|
+
"Uint32BufferAttribute",
|
|
105
|
+
"Uint16BufferAttribute",
|
|
106
|
+
"Int32BufferAttribute",
|
|
107
|
+
# Textures
|
|
108
|
+
"TextTexture",
|
|
109
|
+
]
|
anythreejs/core/base.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base classes for Three.js objects with observable properties.
|
|
3
|
+
|
|
4
|
+
All Three.js objects inherit from these base classes which provide:
|
|
5
|
+
- Property change observation (like ipywidgets traitlets)
|
|
6
|
+
- Serialization to dict for JSON transport to JavaScript
|
|
7
|
+
- UUID for object identification
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any, Callable, Optional
|
|
11
|
+
import uuid
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ThreeJSBase:
|
|
15
|
+
"""
|
|
16
|
+
Base class for all Three.js object representations.
|
|
17
|
+
|
|
18
|
+
Provides observable properties and serialization.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
_type: str = "Object3D"
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
self._uuid = str(uuid.uuid4())
|
|
25
|
+
self._observers: dict[str, list[Callable]] = {}
|
|
26
|
+
self._parent_renderer: Optional[Any] = None
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def uuid(self) -> str:
|
|
30
|
+
return self._uuid
|
|
31
|
+
|
|
32
|
+
def observe(self, handler: Callable, names: list[str] | str = None):
|
|
33
|
+
"""Register an observer for property changes."""
|
|
34
|
+
if isinstance(names, str):
|
|
35
|
+
names = [names]
|
|
36
|
+
if names is None:
|
|
37
|
+
names = ["_all"]
|
|
38
|
+
for name in names:
|
|
39
|
+
if name not in self._observers:
|
|
40
|
+
self._observers[name] = []
|
|
41
|
+
self._observers[name].append(handler)
|
|
42
|
+
|
|
43
|
+
def unobserve(self, handler: Callable, names: list[str] | str = None):
|
|
44
|
+
"""Unregister an observer."""
|
|
45
|
+
if isinstance(names, str):
|
|
46
|
+
names = [names]
|
|
47
|
+
if names is None:
|
|
48
|
+
names = list(self._observers.keys())
|
|
49
|
+
for name in names:
|
|
50
|
+
if name in self._observers and handler in self._observers[name]:
|
|
51
|
+
self._observers[name].remove(handler)
|
|
52
|
+
|
|
53
|
+
def _notify(self, name: str, old: Any, new: Any):
|
|
54
|
+
"""Notify observers of a property change."""
|
|
55
|
+
change = {"name": name, "old": old, "new": new, "owner": self}
|
|
56
|
+
|
|
57
|
+
for handler in self._observers.get(name, []):
|
|
58
|
+
handler(change)
|
|
59
|
+
for handler in self._observers.get("_all", []):
|
|
60
|
+
handler(change)
|
|
61
|
+
|
|
62
|
+
if self._parent_renderer is not None:
|
|
63
|
+
self._parent_renderer._request_render()
|
|
64
|
+
|
|
65
|
+
def _set_renderer(self, renderer):
|
|
66
|
+
"""Set the parent renderer for sync."""
|
|
67
|
+
self._parent_renderer = renderer
|
|
68
|
+
|
|
69
|
+
def to_dict(self) -> dict[str, Any]:
|
|
70
|
+
"""Serialize to dictionary for JSON transport."""
|
|
71
|
+
return {"type": self._type, "uuid": self._uuid}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Object3D(ThreeJSBase):
|
|
75
|
+
"""
|
|
76
|
+
Base class for all 3D objects with transform properties.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
_type = "Object3D"
|
|
80
|
+
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
position: tuple | list = (0, 0, 0),
|
|
84
|
+
rotation: tuple | list = (0, 0, 0),
|
|
85
|
+
scale: tuple | list = (1, 1, 1),
|
|
86
|
+
visible: bool = True,
|
|
87
|
+
name: str = "",
|
|
88
|
+
**kwargs,
|
|
89
|
+
):
|
|
90
|
+
super().__init__()
|
|
91
|
+
self._position = list(position)
|
|
92
|
+
self._rotation = list(rotation)
|
|
93
|
+
self._scale = list(scale)
|
|
94
|
+
self._visible = visible
|
|
95
|
+
self._name = name
|
|
96
|
+
self._children: list["Object3D"] = []
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def position(self) -> tuple:
|
|
100
|
+
return tuple(self._position)
|
|
101
|
+
|
|
102
|
+
@position.setter
|
|
103
|
+
def position(self, value):
|
|
104
|
+
old = self._position
|
|
105
|
+
self._position = list(value)
|
|
106
|
+
self._notify("position", old, self._position)
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def rotation(self) -> list:
|
|
110
|
+
return self._rotation
|
|
111
|
+
|
|
112
|
+
@rotation.setter
|
|
113
|
+
def rotation(self, value):
|
|
114
|
+
old = self._rotation
|
|
115
|
+
self._rotation = list(value)
|
|
116
|
+
self._notify("rotation", old, self._rotation)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def scale(self) -> list:
|
|
120
|
+
return self._scale
|
|
121
|
+
|
|
122
|
+
@scale.setter
|
|
123
|
+
def scale(self, value):
|
|
124
|
+
old = self._scale
|
|
125
|
+
self._scale = list(value)
|
|
126
|
+
self._notify("scale", old, self._scale)
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def visible(self) -> bool:
|
|
130
|
+
return self._visible
|
|
131
|
+
|
|
132
|
+
@visible.setter
|
|
133
|
+
def visible(self, value: bool):
|
|
134
|
+
old = self._visible
|
|
135
|
+
self._visible = value
|
|
136
|
+
self._notify("visible", old, value)
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def name(self) -> str:
|
|
140
|
+
return self._name
|
|
141
|
+
|
|
142
|
+
@name.setter
|
|
143
|
+
def name(self, value: str):
|
|
144
|
+
old = self._name
|
|
145
|
+
self._name = value
|
|
146
|
+
self._notify("name", old, value)
|
|
147
|
+
|
|
148
|
+
def rotateX(self, angle: float) -> "Object3D":
|
|
149
|
+
"""Rotate around X axis by angle (radians)."""
|
|
150
|
+
self._rotation[0] += angle
|
|
151
|
+
self._notify("rotation", None, self._rotation)
|
|
152
|
+
return self
|
|
153
|
+
|
|
154
|
+
def rotateY(self, angle: float) -> "Object3D":
|
|
155
|
+
"""Rotate around Y axis by angle (radians)."""
|
|
156
|
+
self._rotation[1] += angle
|
|
157
|
+
self._notify("rotation", None, self._rotation)
|
|
158
|
+
return self
|
|
159
|
+
|
|
160
|
+
def rotateZ(self, angle: float) -> "Object3D":
|
|
161
|
+
"""Rotate around Z axis by angle (radians)."""
|
|
162
|
+
self._rotation[2] += angle
|
|
163
|
+
self._notify("rotation", None, self._rotation)
|
|
164
|
+
return self
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def children(self) -> list:
|
|
168
|
+
return self._children
|
|
169
|
+
|
|
170
|
+
def add(self, *objects: "Object3D"):
|
|
171
|
+
"""Add child objects. Handles both individual objects and lists."""
|
|
172
|
+
for obj in objects:
|
|
173
|
+
if isinstance(obj, (list, tuple)):
|
|
174
|
+
self.add(*obj)
|
|
175
|
+
elif obj not in self._children:
|
|
176
|
+
self._children.append(obj)
|
|
177
|
+
if self._parent_renderer:
|
|
178
|
+
obj._set_renderer(self._parent_renderer)
|
|
179
|
+
self._notify("children", None, self._children)
|
|
180
|
+
|
|
181
|
+
def remove(self, *objects: "Object3D"):
|
|
182
|
+
"""Remove child objects. Handles both individual objects and lists."""
|
|
183
|
+
for obj in objects:
|
|
184
|
+
if isinstance(obj, (list, tuple)):
|
|
185
|
+
self.remove(*obj)
|
|
186
|
+
elif obj in self._children:
|
|
187
|
+
self._children.remove(obj)
|
|
188
|
+
obj._set_renderer(None)
|
|
189
|
+
self._notify("children", None, self._children)
|
|
190
|
+
|
|
191
|
+
def _set_renderer(self, renderer):
|
|
192
|
+
"""Recursively set renderer on self and children."""
|
|
193
|
+
super()._set_renderer(renderer)
|
|
194
|
+
for child in self._children:
|
|
195
|
+
child._set_renderer(renderer)
|
|
196
|
+
|
|
197
|
+
def to_dict(self) -> dict[str, Any]:
|
|
198
|
+
data = super().to_dict()
|
|
199
|
+
data.update(
|
|
200
|
+
{
|
|
201
|
+
"position": self._position,
|
|
202
|
+
"rotation": self._rotation,
|
|
203
|
+
"scale": self._scale,
|
|
204
|
+
"visible": self._visible,
|
|
205
|
+
"name": self._name,
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
if self._children:
|
|
209
|
+
data["children"] = [child.to_dict() for child in self._children]
|
|
210
|
+
return data
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Buffer attribute classes for custom geometry data.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional, Callable, Union
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BufferAttribute:
|
|
10
|
+
"""Stores data for BufferGeometry attributes."""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
array: Union[list, np.ndarray],
|
|
15
|
+
itemSize: int = 3,
|
|
16
|
+
normalized: bool = False,
|
|
17
|
+
dtype: str = "float32",
|
|
18
|
+
):
|
|
19
|
+
self._array = (
|
|
20
|
+
np.array(array, dtype=dtype) if not isinstance(array, np.ndarray) else array
|
|
21
|
+
)
|
|
22
|
+
self._itemSize = itemSize
|
|
23
|
+
self._normalized = normalized
|
|
24
|
+
self._dtype = dtype
|
|
25
|
+
self._on_change: Optional[Callable] = None
|
|
26
|
+
|
|
27
|
+
def _set_on_change(self, callback: Optional[Callable]):
|
|
28
|
+
self._on_change = callback
|
|
29
|
+
|
|
30
|
+
def _notify_change(self):
|
|
31
|
+
if self._on_change:
|
|
32
|
+
self._on_change()
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def array(self) -> np.ndarray:
|
|
36
|
+
return self._array
|
|
37
|
+
|
|
38
|
+
@array.setter
|
|
39
|
+
def array(self, value):
|
|
40
|
+
self._array = (
|
|
41
|
+
np.array(value, dtype=self._dtype)
|
|
42
|
+
if not isinstance(value, np.ndarray)
|
|
43
|
+
else value
|
|
44
|
+
)
|
|
45
|
+
self._notify_change()
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def itemSize(self) -> int:
|
|
49
|
+
return self._itemSize
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def normalized(self) -> bool:
|
|
53
|
+
return self._normalized
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def count(self) -> int:
|
|
57
|
+
return len(self._array) // self._itemSize
|
|
58
|
+
|
|
59
|
+
def to_dict(self) -> dict[str, Any]:
|
|
60
|
+
arr = (
|
|
61
|
+
self._array.flatten().tolist()
|
|
62
|
+
if hasattr(self._array, "tolist")
|
|
63
|
+
else self._array
|
|
64
|
+
)
|
|
65
|
+
return {
|
|
66
|
+
"array": arr,
|
|
67
|
+
"itemSize": self._itemSize,
|
|
68
|
+
"normalized": self._normalized,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Float32BufferAttribute(BufferAttribute):
|
|
73
|
+
def __init__(self, array, itemSize: int = 3, normalized: bool = False):
|
|
74
|
+
super().__init__(array, itemSize, normalized, dtype="float32")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Uint32BufferAttribute(BufferAttribute):
|
|
78
|
+
def __init__(self, array, itemSize: int = 1, normalized: bool = False):
|
|
79
|
+
super().__init__(array, itemSize, normalized, dtype="uint32")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Uint16BufferAttribute(BufferAttribute):
|
|
83
|
+
def __init__(self, array, itemSize: int = 1, normalized: bool = False):
|
|
84
|
+
super().__init__(array, itemSize, normalized, dtype="uint16")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Int32BufferAttribute(BufferAttribute):
|
|
88
|
+
def __init__(self, array, itemSize: int = 1, normalized: bool = False):
|
|
89
|
+
super().__init__(array, itemSize, normalized, dtype="int32")
|