bplinejs 0.0.101-beta.10
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.
- package/README.md +215 -0
- package/docs/API.md +471 -0
- package/lib/Camera/index.d.ts +88 -0
- package/lib/Camera/index.js +178 -0
- package/lib/Camera/index.js.map +1 -0
- package/lib/Color/index.d.ts +99 -0
- package/lib/Color/index.js +178 -0
- package/lib/Color/index.js.map +1 -0
- package/lib/Geometry/Geo.d.ts +131 -0
- package/lib/Geometry/Geo.js +180 -0
- package/lib/Geometry/Geo.js.map +1 -0
- package/lib/Geometry/Poly2D.d.ts +53 -0
- package/lib/Geometry/Poly2D.js +133 -0
- package/lib/Geometry/Poly2D.js.map +1 -0
- package/lib/Geometry/Rect2d.d.ts +89 -0
- package/lib/Geometry/Rect2d.js +128 -0
- package/lib/Geometry/Rect2d.js.map +1 -0
- package/lib/Geometry/index.d.ts +6 -0
- package/lib/Geometry/index.js +4 -0
- package/lib/Group/index.d.ts +70 -0
- package/lib/Group/index.js +110 -0
- package/lib/Group/index.js.map +1 -0
- package/lib/ID.d.ts +6 -0
- package/lib/ID.js +15 -0
- package/lib/ID.js.map +1 -0
- package/lib/IMesh/index.d.ts +104 -0
- package/lib/IMesh/index.js +333 -0
- package/lib/IMesh/index.js.map +1 -0
- package/lib/Material/Material.d.ts +158 -0
- package/lib/Material/Material.js +229 -0
- package/lib/Material/Material.js.map +1 -0
- package/lib/Material/baseMaterial.d.ts +15 -0
- package/lib/Material/baseMaterial.js +24 -0
- package/lib/Material/baseMaterial.js.map +1 -0
- package/lib/Material/index.d.ts +4 -0
- package/lib/Material/index.js +3 -0
- package/lib/Material/shaders/base/poly/fragment.js +6 -0
- package/lib/Material/shaders/base/poly/fragment.js.map +1 -0
- package/lib/Material/shaders/base/poly/vertex.js +6 -0
- package/lib/Material/shaders/base/poly/vertex.js.map +1 -0
- package/lib/Material/shaders/base/rect/fragment.js +6 -0
- package/lib/Material/shaders/base/rect/fragment.js.map +1 -0
- package/lib/Material/shaders/base/rect/vertex.js +6 -0
- package/lib/Material/shaders/base/rect/vertex.js.map +1 -0
- package/lib/Material/shaders/line/fragment.js +6 -0
- package/lib/Material/shaders/line/fragment.js.map +1 -0
- package/lib/Material/shaders/line/vertex.js +6 -0
- package/lib/Material/shaders/line/vertex.js.map +1 -0
- package/lib/Mesh/index.d.ts +154 -0
- package/lib/Mesh/index.js +254 -0
- package/lib/Mesh/index.js.map +1 -0
- package/lib/Object/index.d.ts +95 -0
- package/lib/Object/index.js +212 -0
- package/lib/Object/index.js.map +1 -0
- package/lib/Raws/index.d.ts +87 -0
- package/lib/Raws/index.js +164 -0
- package/lib/Raws/index.js.map +1 -0
- package/lib/Render/BufferManager.d.ts +93 -0
- package/lib/Render/BufferManager.js +281 -0
- package/lib/Render/BufferManager.js.map +1 -0
- package/lib/Render/DepthManager.d.ts +22 -0
- package/lib/Render/DepthManager.js +95 -0
- package/lib/Render/DepthManager.js.map +1 -0
- package/lib/Render/DestroyManager.d.ts +74 -0
- package/lib/Render/DestroyManager.js +221 -0
- package/lib/Render/DestroyManager.js.map +1 -0
- package/lib/Render/DevelopmentValidator.d.ts +73 -0
- package/lib/Render/DevelopmentValidator.js +188 -0
- package/lib/Render/DevelopmentValidator.js.map +1 -0
- package/lib/Render/DrawCallManager.d.ts +58 -0
- package/lib/Render/DrawCallManager.js +267 -0
- package/lib/Render/DrawCallManager.js.map +1 -0
- package/lib/Render/PipelineManager.d.ts +46 -0
- package/lib/Render/PipelineManager.js +254 -0
- package/lib/Render/PipelineManager.js.map +1 -0
- package/lib/Render/SamplerManager.d.ts +26 -0
- package/lib/Render/SamplerManager.js +42 -0
- package/lib/Render/SamplerManager.js.map +1 -0
- package/lib/Render/SceneUpdate.d.ts +9 -0
- package/lib/Render/SceneUpdate.js +18 -0
- package/lib/Render/SceneUpdate.js.map +1 -0
- package/lib/Render/TextureManager.d.ts +33 -0
- package/lib/Render/TextureManager.js +152 -0
- package/lib/Render/TextureManager.js.map +1 -0
- package/lib/Render/index.d.ts +212 -0
- package/lib/Render/index.js +347 -0
- package/lib/Render/index.js.map +1 -0
- package/lib/Render/types.d.ts +191 -0
- package/lib/Scene/index.d.ts +124 -0
- package/lib/Scene/index.js +225 -0
- package/lib/Scene/index.js.map +1 -0
- package/lib/Style/EdgeStyle.d.ts +28 -0
- package/lib/Style/EdgeStyle.js +67 -0
- package/lib/Style/EdgeStyle.js.map +1 -0
- package/lib/Style/JoinStyle.d.ts +27 -0
- package/lib/Style/JoinStyle.js +53 -0
- package/lib/Style/JoinStyle.js.map +1 -0
- package/lib/Style/PartStyle.d.ts +50 -0
- package/lib/Style/PartStyle.js +92 -0
- package/lib/Style/PartStyle.js.map +1 -0
- package/lib/Style/PointsStyle.d.ts +43 -0
- package/lib/Style/PointsStyle.js +98 -0
- package/lib/Style/PointsStyle.js.map +1 -0
- package/lib/Style/SolidStyle.d.ts +37 -0
- package/lib/Style/SolidStyle.js +83 -0
- package/lib/Style/SolidStyle.js.map +1 -0
- package/lib/Style/TexturedStyle.d.ts +29 -0
- package/lib/Style/TexturedStyle.js +66 -0
- package/lib/Style/TexturedStyle.js.map +1 -0
- package/lib/Style/WireframeStyle.d.ts +7 -0
- package/lib/Style/WireframeStyle.js +13 -0
- package/lib/Style/WireframeStyle.js.map +1 -0
- package/lib/Style/WriteStyleData.d.ts +10 -0
- package/lib/Style/WriteStyleData.js +59 -0
- package/lib/Style/WriteStyleData.js.map +1 -0
- package/lib/Style/index.d.ts +50 -0
- package/lib/Style/index.js +92 -0
- package/lib/Style/index.js.map +1 -0
- package/lib/Style/types.d.ts +21 -0
- package/lib/Texture/Layers.d.ts +26 -0
- package/lib/Texture/Layers.js +42 -0
- package/lib/Texture/Layers.js.map +1 -0
- package/lib/Texture/index.d.ts +116 -0
- package/lib/Texture/index.js +198 -0
- package/lib/Texture/index.js.map +1 -0
- package/lib/global-types.d.ts +8 -0
- package/lib/index.d.ts +43 -0
- package/lib/index.js +34 -0
- package/package.json +130 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import ObjectNode from "../Object/index.js";
|
|
2
|
+
import { Mat3 } from "bpmatrixjs/Math/Mat3";
|
|
3
|
+
//#region src/scripts/Camera/index.ts
|
|
4
|
+
/** 正交相机:输入沿用节点单一版本,矩阵与每个 Render 独立保存处理快照。 */
|
|
5
|
+
var Camera = class extends ObjectNode {
|
|
6
|
+
/** 对象类型。 */
|
|
7
|
+
type = "Camera";
|
|
8
|
+
_width;
|
|
9
|
+
_height;
|
|
10
|
+
_zoom;
|
|
11
|
+
_orthogonalMatrix = new Mat3();
|
|
12
|
+
_viewMatrix = new Mat3();
|
|
13
|
+
_projectionSnapshot = -1;
|
|
14
|
+
_viewWorldMatrix;
|
|
15
|
+
_viewWorldVersion = -1;
|
|
16
|
+
_writingCamera = false;
|
|
17
|
+
/** 保留的缓冲描述;实际 GPUBuffer 仍由 Render 持有。 */
|
|
18
|
+
buffers = {};
|
|
19
|
+
/** @param width 视口宽度 @param height 视口高度 @param zoom 缩放值 */
|
|
20
|
+
constructor(width = 100, height = 100, zoom = 1) {
|
|
21
|
+
super(0, 0);
|
|
22
|
+
this._width = width;
|
|
23
|
+
this._height = height;
|
|
24
|
+
this._zoom = zoom;
|
|
25
|
+
this._orthogonalMatrix.add(this, "orthogonalMatrix");
|
|
26
|
+
this._viewMatrix.add(this, "viewMatrix");
|
|
27
|
+
this.updateCameraMatrix();
|
|
28
|
+
}
|
|
29
|
+
/** 视口宽度。 */
|
|
30
|
+
get width() {
|
|
31
|
+
return this._width;
|
|
32
|
+
}
|
|
33
|
+
/** @param value 新宽度 */
|
|
34
|
+
set width(value) {
|
|
35
|
+
if (this._width === value) return;
|
|
36
|
+
this._width = value;
|
|
37
|
+
this.updateVersion();
|
|
38
|
+
}
|
|
39
|
+
/** 视口高度。 */
|
|
40
|
+
get height() {
|
|
41
|
+
return this._height;
|
|
42
|
+
}
|
|
43
|
+
/** @param value 新高度 */
|
|
44
|
+
set height(value) {
|
|
45
|
+
if (this._height === value) return;
|
|
46
|
+
this._height = value;
|
|
47
|
+
this.updateVersion();
|
|
48
|
+
}
|
|
49
|
+
/** 相机缩放。 */
|
|
50
|
+
get zoom() {
|
|
51
|
+
return this._zoom;
|
|
52
|
+
}
|
|
53
|
+
/** @param value 新缩放 */
|
|
54
|
+
set zoom(value) {
|
|
55
|
+
if (this._zoom === value) return;
|
|
56
|
+
this._zoom = value;
|
|
57
|
+
this.updateVersion();
|
|
58
|
+
}
|
|
59
|
+
/** 正交视口上边界。 */
|
|
60
|
+
get top() {
|
|
61
|
+
return this.height * .5 / this.zoom;
|
|
62
|
+
}
|
|
63
|
+
/** 正交视口下边界。 */
|
|
64
|
+
get bottom() {
|
|
65
|
+
return -this.height * .5 / this.zoom;
|
|
66
|
+
}
|
|
67
|
+
/** 正交视口左边界。 */
|
|
68
|
+
get left() {
|
|
69
|
+
return -this.width * .5 / this.zoom;
|
|
70
|
+
}
|
|
71
|
+
/** 正交视口右边界。 */
|
|
72
|
+
get right() {
|
|
73
|
+
return this.width * .5 / this.zoom;
|
|
74
|
+
}
|
|
75
|
+
/** 投影矩阵,GPU 上传比较矩阵版本。 */
|
|
76
|
+
get orthogonalMatrix() {
|
|
77
|
+
return this._orthogonalMatrix;
|
|
78
|
+
}
|
|
79
|
+
/** @param value 新投影矩阵,替换引用也使 Render 缓存失效 */
|
|
80
|
+
set orthogonalMatrix(value) {
|
|
81
|
+
if (this._orthogonalMatrix === value) return;
|
|
82
|
+
this._orthogonalMatrix.delete(this, "orthogonalMatrix");
|
|
83
|
+
this._orthogonalMatrix = value;
|
|
84
|
+
value.add(this, "orthogonalMatrix");
|
|
85
|
+
this.onMathChange(value, "orthogonalMatrix");
|
|
86
|
+
}
|
|
87
|
+
/** 视图矩阵,通常为世界矩阵的逆。 */
|
|
88
|
+
get viewMatrix() {
|
|
89
|
+
return this._viewMatrix;
|
|
90
|
+
}
|
|
91
|
+
/** @param value 新视图矩阵 */
|
|
92
|
+
set viewMatrix(value) {
|
|
93
|
+
if (this._viewMatrix === value) return;
|
|
94
|
+
this._viewMatrix.delete(this, "viewMatrix");
|
|
95
|
+
this._viewMatrix = value;
|
|
96
|
+
value.add(this, "viewMatrix");
|
|
97
|
+
this.onMathChange(value, "viewMatrix");
|
|
98
|
+
}
|
|
99
|
+
/** @param source 数学对象 @param field 关联字段 */
|
|
100
|
+
onMathChange(source, field) {
|
|
101
|
+
if (this._nodeDisposed) return;
|
|
102
|
+
if (field === "orthogonalMatrix" && source === this._orthogonalMatrix || field === "viewMatrix" && source === this._viewMatrix) {
|
|
103
|
+
if (this._writingCamera) return;
|
|
104
|
+
this.updateVersion();
|
|
105
|
+
if (field === "orthogonalMatrix") this._projectionSnapshot = this.version;
|
|
106
|
+
else {
|
|
107
|
+
this._viewWorldMatrix = this.worldMatrix;
|
|
108
|
+
this._viewWorldVersion = this.worldMatrix.version;
|
|
109
|
+
}
|
|
110
|
+
} else super.onMathChange(source, field);
|
|
111
|
+
}
|
|
112
|
+
/** @param width 新视口宽度 @param height 新视口高度 */
|
|
113
|
+
setViewport(width = 100, height = 100) {
|
|
114
|
+
if (this._width === width && this._height === height) return;
|
|
115
|
+
this._width = width;
|
|
116
|
+
this._height = height;
|
|
117
|
+
this.updateVersion();
|
|
118
|
+
}
|
|
119
|
+
/** 相机不提供子节点容器。 */
|
|
120
|
+
add() {
|
|
121
|
+
throw new Error("Camera does not support add().");
|
|
122
|
+
}
|
|
123
|
+
/** 在渲染前更新版本落后的矩阵;支持相机挂在 Group/Mesh 内以及独立相机。 */
|
|
124
|
+
ensureCameraMatrix() {
|
|
125
|
+
this.ensureWorldMatrix();
|
|
126
|
+
if (this._projectionSnapshot !== this.version) this.updateOrthogonalMatrix();
|
|
127
|
+
if (this._viewWorldMatrix !== this.worldMatrix || this._viewWorldVersion !== this.worldMatrix.version) this.updateViewMatrix();
|
|
128
|
+
}
|
|
129
|
+
/** 强制计算投影矩阵,保持 Y 正方向向上。 */
|
|
130
|
+
updateOrthogonalMatrix() {
|
|
131
|
+
this._writingCamera = true;
|
|
132
|
+
try {
|
|
133
|
+
this._orthogonalMatrix.set([
|
|
134
|
+
2 * this.zoom / this.width,
|
|
135
|
+
0,
|
|
136
|
+
0,
|
|
137
|
+
0,
|
|
138
|
+
2 * this.zoom / this.height,
|
|
139
|
+
0,
|
|
140
|
+
0,
|
|
141
|
+
0,
|
|
142
|
+
1
|
|
143
|
+
]);
|
|
144
|
+
this._projectionSnapshot = this.version;
|
|
145
|
+
} finally {
|
|
146
|
+
this._writingCamera = false;
|
|
147
|
+
}
|
|
148
|
+
return this._orthogonalMatrix;
|
|
149
|
+
}
|
|
150
|
+
/** 先确保父级与自身世界矩阵有效,再计算逆矩阵。 */
|
|
151
|
+
updateViewMatrix() {
|
|
152
|
+
this.ensureWorldMatrix();
|
|
153
|
+
this._writingCamera = true;
|
|
154
|
+
try {
|
|
155
|
+
this._viewMatrix.copy(this.worldMatrix).invert();
|
|
156
|
+
this._viewWorldMatrix = this.worldMatrix;
|
|
157
|
+
this._viewWorldVersion = this.worldMatrix.version;
|
|
158
|
+
} finally {
|
|
159
|
+
this._writingCamera = false;
|
|
160
|
+
}
|
|
161
|
+
return this._viewMatrix;
|
|
162
|
+
}
|
|
163
|
+
/** 强制更新投影矩阵和视图矩阵。 */
|
|
164
|
+
updateCameraMatrix() {
|
|
165
|
+
this.updateOrthogonalMatrix();
|
|
166
|
+
this.updateViewMatrix();
|
|
167
|
+
}
|
|
168
|
+
/** 最终释放相机对所有数学对象的订阅,不销毁共享矩阵。 */
|
|
169
|
+
dispose() {
|
|
170
|
+
this._orthogonalMatrix.delete(this, "orthogonalMatrix");
|
|
171
|
+
this._viewMatrix.delete(this, "viewMatrix");
|
|
172
|
+
super.dispose();
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
//#endregion
|
|
176
|
+
export { Camera as default };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/scripts/Camera/index.ts"],"sourcesContent":["import ObjectNode from \"../Object\";\nimport type { ObjectNodeLike } from \"../Object\";\nimport { Mat3 } from \"bpmatrixjs/Math/Mat3\";\nimport type { VersionedMath } from \"bpmatrixjs/Math\";\n\ninterface CameraBuffersLike {\n uniform?: number;\n}\ninterface CameraLike extends ObjectNodeLike {\n zoom: number;\n width: number;\n height: number;\n orthogonalMatrix: Mat3;\n viewMatrix: Mat3;\n buffers: CameraBuffersLike;\n readonly top: number;\n readonly left: number;\n readonly bottom: number;\n readonly right: number;\n setViewport(width: number, height: number): void;\n ensureCameraMatrix(): void;\n updateOrthogonalMatrix(): Mat3;\n updateViewMatrix(): Mat3;\n updateCameraMatrix(): void;\n}\n\n/** 正交相机:输入沿用节点单一版本,矩阵与每个 Render 独立保存处理快照。 */\nclass Camera extends ObjectNode implements CameraLike {\n /** 对象类型。 */\n public readonly type: string = \"Camera\";\n private _width: number;\n private _height: number;\n private _zoom: number;\n private _orthogonalMatrix = new Mat3();\n private _viewMatrix = new Mat3();\n private _projectionSnapshot: number = -1;\n private _viewWorldMatrix: Mat3 | undefined;\n private _viewWorldVersion: number = -1;\n private _writingCamera: boolean = false;\n /** 保留的缓冲描述;实际 GPUBuffer 仍由 Render 持有。 */\n public buffers: CameraBuffersLike = {};\n\n /** @param width 视口宽度 @param height 视口高度 @param zoom 缩放值 */\n public constructor(width: number = 100, height: number = 100, zoom: number = 1) {\n super(0, 0);\n this._width = width;\n this._height = height;\n this._zoom = zoom;\n this._orthogonalMatrix.add(this, \"orthogonalMatrix\");\n this._viewMatrix.add(this, \"viewMatrix\");\n this.updateCameraMatrix();\n }\n\n /** 视口宽度。 */\n public get width(): number { return this._width; }\n /** @param value 新宽度 */\n public set width(value: number) {\n if (this._width === value) return;\n this._width = value;\n this.updateVersion();\n }\n /** 视口高度。 */\n public get height(): number { return this._height; }\n /** @param value 新高度 */\n public set height(value: number) {\n if (this._height === value) return;\n this._height = value;\n this.updateVersion();\n }\n /** 相机缩放。 */\n public get zoom(): number { return this._zoom; }\n /** @param value 新缩放 */\n public set zoom(value: number) {\n if (this._zoom === value) return;\n this._zoom = value;\n this.updateVersion();\n }\n /** 正交视口上边界。 */\n public get top(): number { return this.height * 0.5 / this.zoom; }\n /** 正交视口下边界。 */\n public get bottom(): number { return -this.height * 0.5 / this.zoom; }\n /** 正交视口左边界。 */\n public get left(): number { return -this.width * 0.5 / this.zoom; }\n /** 正交视口右边界。 */\n public get right(): number { return this.width * 0.5 / this.zoom; }\n\n /** 投影矩阵,GPU 上传比较矩阵版本。 */\n public get orthogonalMatrix(): Mat3 { return this._orthogonalMatrix; }\n /** @param value 新投影矩阵,替换引用也使 Render 缓存失效 */\n public set orthogonalMatrix(value: Mat3) {\n if (this._orthogonalMatrix === value) return;\n this._orthogonalMatrix.delete(this, \"orthogonalMatrix\");\n this._orthogonalMatrix = value;\n value.add(this, \"orthogonalMatrix\");\n this.onMathChange(value, \"orthogonalMatrix\");\n }\n /** 视图矩阵,通常为世界矩阵的逆。 */\n public get viewMatrix(): Mat3 { return this._viewMatrix; }\n /** @param value 新视图矩阵 */\n public set viewMatrix(value: Mat3) {\n if (this._viewMatrix === value) return;\n this._viewMatrix.delete(this, \"viewMatrix\");\n this._viewMatrix = value;\n value.add(this, \"viewMatrix\");\n this.onMathChange(value, \"viewMatrix\");\n }\n\n /** @param source 数学对象 @param field 关联字段 */\n public override onMathChange(source: VersionedMath, field: string): void {\n if (this._nodeDisposed) return;\n if ((field === \"orthogonalMatrix\" && source === this._orthogonalMatrix)\n || (field === \"viewMatrix\" && source === this._viewMatrix)) {\n if (this._writingCamera) return;\n this.updateVersion();\n if (field === \"orthogonalMatrix\") this._projectionSnapshot = this.version;\n else {\n this._viewWorldMatrix = this.worldMatrix;\n this._viewWorldVersion = this.worldMatrix.version;\n }\n } else super.onMathChange(source, field);\n }\n\n /** @param width 新视口宽度 @param height 新视口高度 */\n public setViewport(width: number = 100, height: number = 100): void {\n if (this._width === width && this._height === height) return;\n this._width = width;\n this._height = height;\n this.updateVersion();\n }\n /** 相机不提供子节点容器。 */\n public add(): void { throw new Error(\"Camera does not support add().\"); }\n\n /** 在渲染前更新版本落后的矩阵;支持相机挂在 Group/Mesh 内以及独立相机。 */\n public ensureCameraMatrix(): void {\n this.ensureWorldMatrix();\n if (this._projectionSnapshot !== this.version) this.updateOrthogonalMatrix();\n if (this._viewWorldMatrix !== this.worldMatrix || this._viewWorldVersion !== this.worldMatrix.version) {\n this.updateViewMatrix();\n }\n }\n\n /** 强制计算投影矩阵,保持 Y 正方向向上。 */\n public updateOrthogonalMatrix(): Mat3 {\n this._writingCamera = true;\n try {\n this._orthogonalMatrix.set([\n 2 * this.zoom / this.width, 0, 0,\n 0, 2 * this.zoom / this.height, 0,\n 0, 0, 1,\n ]);\n this._projectionSnapshot = this.version;\n } finally {\n this._writingCamera = false;\n }\n return this._orthogonalMatrix;\n }\n\n /** 先确保父级与自身世界矩阵有效,再计算逆矩阵。 */\n public updateViewMatrix(): Mat3 {\n this.ensureWorldMatrix();\n this._writingCamera = true;\n try {\n this._viewMatrix.copy(this.worldMatrix).invert();\n this._viewWorldMatrix = this.worldMatrix;\n this._viewWorldVersion = this.worldMatrix.version;\n } finally {\n this._writingCamera = false;\n }\n return this._viewMatrix;\n }\n\n /** 强制更新投影矩阵和视图矩阵。 */\n public updateCameraMatrix(): void {\n this.updateOrthogonalMatrix();\n this.updateViewMatrix();\n }\n\n /** 最终释放相机对所有数学对象的订阅,不销毁共享矩阵。 */\n public override dispose(): void {\n this._orthogonalMatrix.delete(this, \"orthogonalMatrix\");\n this._viewMatrix.delete(this, \"viewMatrix\");\n super.dispose();\n }\n}\nexport default Camera;\nexport type { CameraBuffersLike, CameraLike };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/** 接收颜色变化的对象;字段标识允许同一对象的多个属性共用一个 Color。 */
|
|
2
|
+
export interface ColorSubscriber {
|
|
3
|
+
onColorChange(color: Color, field: string): void;
|
|
4
|
+
}
|
|
5
|
+
/** 归一化 RGBA 颜色;所有修改入口都会在值实际变化后通知订阅者。 */
|
|
6
|
+
declare class Color {
|
|
7
|
+
private readonly _data;
|
|
8
|
+
private readonly _subscribers;
|
|
9
|
+
/**
|
|
10
|
+
* 创建颜色,默认不透明白色;数字十六进制按 RRGGBB 解释。
|
|
11
|
+
* @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB
|
|
12
|
+
*/
|
|
13
|
+
constructor(hex?: string | number);
|
|
14
|
+
/** 获取红分量,范围 0 到 1。 */
|
|
15
|
+
get r(): number;
|
|
16
|
+
/**
|
|
17
|
+
* 设置红分量,有限值会钳制到 0 到 1。
|
|
18
|
+
* @param value 归一化分量
|
|
19
|
+
*/
|
|
20
|
+
set r(value: number);
|
|
21
|
+
/** 获取绿分量,范围 0 到 1。 */
|
|
22
|
+
get g(): number;
|
|
23
|
+
/**
|
|
24
|
+
* 设置绿分量,有限值会钳制到 0 到 1。
|
|
25
|
+
* @param value 归一化分量
|
|
26
|
+
*/
|
|
27
|
+
set g(value: number);
|
|
28
|
+
/** 获取蓝分量,范围 0 到 1。 */
|
|
29
|
+
get b(): number;
|
|
30
|
+
/**
|
|
31
|
+
* 设置蓝分量,有限值会钳制到 0 到 1。
|
|
32
|
+
* @param value 归一化分量
|
|
33
|
+
*/
|
|
34
|
+
set b(value: number);
|
|
35
|
+
/** 获取透明度分量,范围 0 到 1。 */
|
|
36
|
+
get a(): number;
|
|
37
|
+
/**
|
|
38
|
+
* 设置透明度分量,有限值会钳制到 0 到 1。
|
|
39
|
+
* @param value 归一化分量
|
|
40
|
+
*/
|
|
41
|
+
set a(value: number);
|
|
42
|
+
/**
|
|
43
|
+
* 批量设置 RGB,保留当前 alpha,只通知一次。
|
|
44
|
+
* @param r 红色,0 到 1
|
|
45
|
+
* @param g 绿色,0 到 1
|
|
46
|
+
* @param b 蓝色,0 到 1
|
|
47
|
+
* @returns 当前颜色
|
|
48
|
+
*/
|
|
49
|
+
setRGB(r: number, g: number, b: number): this;
|
|
50
|
+
/**
|
|
51
|
+
* 批量设置 RGBA,验证成功后统一提交,只通知一次。
|
|
52
|
+
* @param r 红色,0 到 1
|
|
53
|
+
* @param g 绿色,0 到 1
|
|
54
|
+
* @param b 蓝色,0 到 1
|
|
55
|
+
* @param a 透明度,0 到 1
|
|
56
|
+
* @returns 当前颜色
|
|
57
|
+
*/
|
|
58
|
+
setRGBA(r: number, g: number, b: number, a?: number): this;
|
|
59
|
+
/**
|
|
60
|
+
* 设置十六进制颜色;没有 alpha 的格式使用不透明值。
|
|
61
|
+
* @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB
|
|
62
|
+
* @returns 当前颜色
|
|
63
|
+
*/
|
|
64
|
+
setHex(hex: string | number): this;
|
|
65
|
+
/**
|
|
66
|
+
* 转为十六进制文本,不做额外颜色空间变换。
|
|
67
|
+
* @param alpha 是否包含 alpha
|
|
68
|
+
* @returns #rrggbb 或 #rrggbbaa
|
|
69
|
+
*/
|
|
70
|
+
toHex(alpha?: boolean): string;
|
|
71
|
+
/**
|
|
72
|
+
* 将 RGBA 写入调用者数组,不暴露内部可变数据。
|
|
73
|
+
* @param target 目标数组
|
|
74
|
+
* @param offset 分量偏移,不是字节偏移
|
|
75
|
+
* @returns 目标数组
|
|
76
|
+
*/
|
|
77
|
+
writeTo(target: Float32Array<ArrayBuffer>, offset?: number): Float32Array<ArrayBuffer>;
|
|
78
|
+
/**
|
|
79
|
+
* 复制颜色数值,不共享订阅者。
|
|
80
|
+
* @param color 来源颜色
|
|
81
|
+
* @returns 当前颜色
|
|
82
|
+
*/
|
|
83
|
+
copy(color: Color): this;
|
|
84
|
+
/** 创建没有订阅者的独立颜色副本。 */
|
|
85
|
+
clone(): Color;
|
|
86
|
+
/**
|
|
87
|
+
* 登记订阅关系,同一对象的不同颜色字段分别计数。
|
|
88
|
+
* @param subscriber 接收变化的对象
|
|
89
|
+
* @param field 对象内的颜色字段名
|
|
90
|
+
*/
|
|
91
|
+
add(subscriber: ColorSubscriber, field?: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* 解除单个字段订阅;省略字段时解除该对象全部订阅。
|
|
94
|
+
* @param subscriber 接收变化的对象
|
|
95
|
+
* @param field 要解除的颜色字段
|
|
96
|
+
*/
|
|
97
|
+
delete(subscriber: ColorSubscriber, field?: string): void;
|
|
98
|
+
}
|
|
99
|
+
export default Color;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
//#region src/scripts/Color/index.ts
|
|
2
|
+
/** 归一化 RGBA 颜色;所有修改入口都会在值实际变化后通知订阅者。 */
|
|
3
|
+
var Color = class Color {
|
|
4
|
+
_data = [
|
|
5
|
+
1,
|
|
6
|
+
1,
|
|
7
|
+
1,
|
|
8
|
+
1
|
|
9
|
+
];
|
|
10
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
11
|
+
/**
|
|
12
|
+
* 创建颜色,默认不透明白色;数字十六进制按 RRGGBB 解释。
|
|
13
|
+
* @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB
|
|
14
|
+
*/
|
|
15
|
+
constructor(hex = "#ffffff") {
|
|
16
|
+
this.setHex(hex);
|
|
17
|
+
}
|
|
18
|
+
/** 获取红分量,范围 0 到 1。 */
|
|
19
|
+
get r() {
|
|
20
|
+
return this._data[0];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 设置红分量,有限值会钳制到 0 到 1。
|
|
24
|
+
* @param value 归一化分量
|
|
25
|
+
*/
|
|
26
|
+
set r(value) {
|
|
27
|
+
const data = [...this._data];
|
|
28
|
+
data[0] = value;
|
|
29
|
+
this.setRGBA(data[0], data[1], data[2], data[3]);
|
|
30
|
+
}
|
|
31
|
+
/** 获取绿分量,范围 0 到 1。 */
|
|
32
|
+
get g() {
|
|
33
|
+
return this._data[1];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 设置绿分量,有限值会钳制到 0 到 1。
|
|
37
|
+
* @param value 归一化分量
|
|
38
|
+
*/
|
|
39
|
+
set g(value) {
|
|
40
|
+
const data = [...this._data];
|
|
41
|
+
data[1] = value;
|
|
42
|
+
this.setRGBA(data[0], data[1], data[2], data[3]);
|
|
43
|
+
}
|
|
44
|
+
/** 获取蓝分量,范围 0 到 1。 */
|
|
45
|
+
get b() {
|
|
46
|
+
return this._data[2];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 设置蓝分量,有限值会钳制到 0 到 1。
|
|
50
|
+
* @param value 归一化分量
|
|
51
|
+
*/
|
|
52
|
+
set b(value) {
|
|
53
|
+
const data = [...this._data];
|
|
54
|
+
data[2] = value;
|
|
55
|
+
this.setRGBA(data[0], data[1], data[2], data[3]);
|
|
56
|
+
}
|
|
57
|
+
/** 获取透明度分量,范围 0 到 1。 */
|
|
58
|
+
get a() {
|
|
59
|
+
return this._data[3];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 设置透明度分量,有限值会钳制到 0 到 1。
|
|
63
|
+
* @param value 归一化分量
|
|
64
|
+
*/
|
|
65
|
+
set a(value) {
|
|
66
|
+
const data = [...this._data];
|
|
67
|
+
data[3] = value;
|
|
68
|
+
this.setRGBA(data[0], data[1], data[2], data[3]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 批量设置 RGB,保留当前 alpha,只通知一次。
|
|
72
|
+
* @param r 红色,0 到 1
|
|
73
|
+
* @param g 绿色,0 到 1
|
|
74
|
+
* @param b 蓝色,0 到 1
|
|
75
|
+
* @returns 当前颜色
|
|
76
|
+
*/
|
|
77
|
+
setRGB(r, g, b) {
|
|
78
|
+
return this.setRGBA(r, g, b, this.a);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 批量设置 RGBA,验证成功后统一提交,只通知一次。
|
|
82
|
+
* @param r 红色,0 到 1
|
|
83
|
+
* @param g 绿色,0 到 1
|
|
84
|
+
* @param b 蓝色,0 到 1
|
|
85
|
+
* @param a 透明度,0 到 1
|
|
86
|
+
* @returns 当前颜色
|
|
87
|
+
*/
|
|
88
|
+
setRGBA(r, g, b, a = 1) {
|
|
89
|
+
const values = [
|
|
90
|
+
r,
|
|
91
|
+
g,
|
|
92
|
+
b,
|
|
93
|
+
a
|
|
94
|
+
];
|
|
95
|
+
if (!values.every(Number.isFinite)) throw new RangeError("Color components must be finite.");
|
|
96
|
+
const normalized = values.map((value) => Math.min(1, Math.max(0, value)));
|
|
97
|
+
if (normalized.every((value, index) => value === this._data[index])) return this;
|
|
98
|
+
this._data.splice(0, 4, ...normalized);
|
|
99
|
+
for (const [subscriber, fields] of [...this._subscribers]) for (const field of [...fields]) subscriber.onColorChange(this, field);
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 设置十六进制颜色;没有 alpha 的格式使用不透明值。
|
|
104
|
+
* @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB
|
|
105
|
+
* @returns 当前颜色
|
|
106
|
+
*/
|
|
107
|
+
setHex(hex) {
|
|
108
|
+
if (typeof hex === "number" && (!Number.isInteger(hex) || hex < 0 || hex > 16777215)) throw new RangeError("Numeric hex colors must be between 0x000000 and 0xffffff.");
|
|
109
|
+
let text = typeof hex === "number" ? hex.toString(16).padStart(6, "0") : hex.replace(/^#/, "");
|
|
110
|
+
if (!/^(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(text)) throw new TypeError("Invalid hex color.");
|
|
111
|
+
if (text.length <= 4) text = text.replace(/./g, (digit) => digit + digit);
|
|
112
|
+
if (text.length === 6) text += "ff";
|
|
113
|
+
return this.setRGBA(...[
|
|
114
|
+
0,
|
|
115
|
+
2,
|
|
116
|
+
4,
|
|
117
|
+
6
|
|
118
|
+
].map((offset) => parseInt(text.slice(offset, offset + 2), 16) / 255));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 转为十六进制文本,不做额外颜色空间变换。
|
|
122
|
+
* @param alpha 是否包含 alpha
|
|
123
|
+
* @returns #rrggbb 或 #rrggbbaa
|
|
124
|
+
*/
|
|
125
|
+
toHex(alpha = false) {
|
|
126
|
+
return "#" + this._data.slice(0, alpha ? 4 : 3).map((value) => Math.round(value * 255).toString(16).padStart(2, "0")).join("");
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 将 RGBA 写入调用者数组,不暴露内部可变数据。
|
|
130
|
+
* @param target 目标数组
|
|
131
|
+
* @param offset 分量偏移,不是字节偏移
|
|
132
|
+
* @returns 目标数组
|
|
133
|
+
*/
|
|
134
|
+
writeTo(target, offset = 0) {
|
|
135
|
+
target.set(this._data, offset);
|
|
136
|
+
return target;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 复制颜色数值,不共享订阅者。
|
|
140
|
+
* @param color 来源颜色
|
|
141
|
+
* @returns 当前颜色
|
|
142
|
+
*/
|
|
143
|
+
copy(color) {
|
|
144
|
+
return this.setRGBA(color.r, color.g, color.b, color.a);
|
|
145
|
+
}
|
|
146
|
+
/** 创建没有订阅者的独立颜色副本。 */
|
|
147
|
+
clone() {
|
|
148
|
+
return new Color().copy(this);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* 登记订阅关系,同一对象的不同颜色字段分别计数。
|
|
152
|
+
* @param subscriber 接收变化的对象
|
|
153
|
+
* @param field 对象内的颜色字段名
|
|
154
|
+
*/
|
|
155
|
+
add(subscriber, field = "color") {
|
|
156
|
+
const fields = this._subscribers.get(subscriber) ?? /* @__PURE__ */ new Set();
|
|
157
|
+
fields.add(field);
|
|
158
|
+
this._subscribers.set(subscriber, fields);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 解除单个字段订阅;省略字段时解除该对象全部订阅。
|
|
162
|
+
* @param subscriber 接收变化的对象
|
|
163
|
+
* @param field 要解除的颜色字段
|
|
164
|
+
*/
|
|
165
|
+
delete(subscriber, field) {
|
|
166
|
+
if (field === void 0) {
|
|
167
|
+
this._subscribers.delete(subscriber);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const fields = this._subscribers.get(subscriber);
|
|
171
|
+
fields?.delete(field);
|
|
172
|
+
if (fields?.size === 0) this._subscribers.delete(subscriber);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
//#endregion
|
|
176
|
+
export { Color as default };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/scripts/Color/index.ts"],"sourcesContent":["/** 接收颜色变化的对象;字段标识允许同一对象的多个属性共用一个 Color。 */\nexport interface ColorSubscriber {\n onColorChange(color: Color, field: string): void;\n}\n\n/** 归一化 RGBA 颜色;所有修改入口都会在值实际变化后通知订阅者。 */\nclass Color {\n private readonly _data: number[] = [1, 1, 1, 1];\n private readonly _subscribers = new Map<ColorSubscriber, Set<string>>();\n\n /**\n * 创建颜色,默认不透明白色;数字十六进制按 RRGGBB 解释。\n * @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB\n */\n public constructor(hex: string | number = \"#ffffff\") {\n this.setHex(hex);\n }\n\n /** 获取红分量,范围 0 到 1。 */\n public get r(): number { return this._data[0]; }\n /**\n * 设置红分量,有限值会钳制到 0 到 1。\n * @param value 归一化分量\n */\n public set r(value: number) {\n const data = [...this._data];\n data[0] = value;\n this.setRGBA(data[0], data[1], data[2], data[3]);\n }\n\n /** 获取绿分量,范围 0 到 1。 */\n public get g(): number { return this._data[1]; }\n /**\n * 设置绿分量,有限值会钳制到 0 到 1。\n * @param value 归一化分量\n */\n public set g(value: number) {\n const data = [...this._data];\n data[1] = value;\n this.setRGBA(data[0], data[1], data[2], data[3]);\n }\n\n /** 获取蓝分量,范围 0 到 1。 */\n public get b(): number { return this._data[2]; }\n /**\n * 设置蓝分量,有限值会钳制到 0 到 1。\n * @param value 归一化分量\n */\n public set b(value: number) {\n const data = [...this._data];\n data[2] = value;\n this.setRGBA(data[0], data[1], data[2], data[3]);\n }\n\n /** 获取透明度分量,范围 0 到 1。 */\n public get a(): number { return this._data[3]; }\n /**\n * 设置透明度分量,有限值会钳制到 0 到 1。\n * @param value 归一化分量\n */\n public set a(value: number) {\n const data = [...this._data];\n data[3] = value;\n this.setRGBA(data[0], data[1], data[2], data[3]);\n }\n\n /**\n * 批量设置 RGB,保留当前 alpha,只通知一次。\n * @param r 红色,0 到 1\n * @param g 绿色,0 到 1\n * @param b 蓝色,0 到 1\n * @returns 当前颜色\n */\n public setRGB(r: number, g: number, b: number): this {\n return this.setRGBA(r, g, b, this.a);\n }\n\n /**\n * 批量设置 RGBA,验证成功后统一提交,只通知一次。\n * @param r 红色,0 到 1\n * @param g 绿色,0 到 1\n * @param b 蓝色,0 到 1\n * @param a 透明度,0 到 1\n * @returns 当前颜色\n */\n public setRGBA(r: number, g: number, b: number, a: number = 1): this {\n const values = [r, g, b, a];\n if (!values.every(Number.isFinite)) throw new RangeError(\"Color components must be finite.\");\n const normalized = values.map((value: number): number => Math.min(1, Math.max(0, value)));\n if (normalized.every((value: number, index: number): boolean => value === this._data[index])) return this;\n this._data.splice(0, 4, ...normalized);\n for (const [subscriber, fields] of [...this._subscribers]) {\n for (const field of [...fields]) subscriber.onColorChange(this, field);\n }\n return this;\n }\n\n /**\n * 设置十六进制颜色;没有 alpha 的格式使用不透明值。\n * @param hex #RGB、#RGBA、#RRGGBB、#RRGGBBAA 或 0xRRGGBB\n * @returns 当前颜色\n */\n public setHex(hex: string | number): this {\n if (typeof hex === \"number\" && (!Number.isInteger(hex) || hex < 0 || hex > 0xffffff)) {\n throw new RangeError(\"Numeric hex colors must be between 0x000000 and 0xffffff.\");\n }\n let text: string = typeof hex === \"number\" ? hex.toString(16).padStart(6, \"0\") : hex.replace(/^#/, \"\");\n if (!/^(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(text)) {\n throw new TypeError(\"Invalid hex color.\");\n }\n if (text.length <= 4) text = text.replace(/./g, (digit: string): string => digit + digit);\n if (text.length === 6) text += \"ff\";\n return this.setRGBA(...[0, 2, 4, 6].map((offset: number): number => parseInt(text.slice(offset, offset + 2), 16) / 255) as [number, number, number, number]);\n }\n\n /**\n * 转为十六进制文本,不做额外颜色空间变换。\n * @param alpha 是否包含 alpha\n * @returns #rrggbb 或 #rrggbbaa\n */\n public toHex(alpha: boolean = false): string {\n return \"#\" + this._data.slice(0, alpha ? 4 : 3)\n .map((value: number): string => Math.round(value * 255).toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n /**\n * 将 RGBA 写入调用者数组,不暴露内部可变数据。\n * @param target 目标数组\n * @param offset 分量偏移,不是字节偏移\n * @returns 目标数组\n */\n public writeTo(target: Float32Array<ArrayBuffer>, offset: number = 0): Float32Array<ArrayBuffer> {\n target.set(this._data, offset);\n return target;\n }\n\n /**\n * 复制颜色数值,不共享订阅者。\n * @param color 来源颜色\n * @returns 当前颜色\n */\n public copy(color: Color): this { return this.setRGBA(color.r, color.g, color.b, color.a); }\n\n /** 创建没有订阅者的独立颜色副本。 */\n public clone(): Color { return new Color().copy(this); }\n\n /**\n * 登记订阅关系,同一对象的不同颜色字段分别计数。\n * @param subscriber 接收变化的对象\n * @param field 对象内的颜色字段名\n */\n public add(subscriber: ColorSubscriber, field: string = \"color\"): void {\n const fields = this._subscribers.get(subscriber) ?? new Set<string>();\n fields.add(field);\n this._subscribers.set(subscriber, fields);\n }\n\n /**\n * 解除单个字段订阅;省略字段时解除该对象全部订阅。\n * @param subscriber 接收变化的对象\n * @param field 要解除的颜色字段\n */\n public delete(subscriber: ColorSubscriber, field?: string): void {\n if (field === undefined) { this._subscribers.delete(subscriber); return; }\n const fields = this._subscribers.get(subscriber);\n fields?.delete(field);\n if (fields?.size === 0) this._subscribers.delete(subscriber);\n }\n}\nexport default Color;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import Style from "../Style";
|
|
2
|
+
import type { StyleChange, StyleSubscriber } from "../Style";
|
|
3
|
+
/** 边框对齐类型沿用 Style 定义。 */
|
|
4
|
+
import type { BorderAlign } from "../Style";
|
|
5
|
+
interface GeoBuffersLike {
|
|
6
|
+
vertex?: number;
|
|
7
|
+
normal?: number;
|
|
8
|
+
uv?: number;
|
|
9
|
+
index?: number;
|
|
10
|
+
}
|
|
11
|
+
/** 单个几何分区的顶点属性。 */
|
|
12
|
+
interface GeoPartDataLike {
|
|
13
|
+
geometry: Float32Array;
|
|
14
|
+
normal: Float32Array;
|
|
15
|
+
uv: Float32Array;
|
|
16
|
+
index: Uint16Array | Uint32Array;
|
|
17
|
+
/** 点型逐顶点中心坐标,长度与 geometry 相同。 */
|
|
18
|
+
position?: Float32Array;
|
|
19
|
+
/** 每个顶点的用途:0 为实体面,0.5 为宽边框,1 为关键点。 */
|
|
20
|
+
vertexType?: Float32Array;
|
|
21
|
+
miterScale?: Float32Array;
|
|
22
|
+
}
|
|
23
|
+
/** 几何消费者;通知只标记后续工作,不在回调中生成几何或操作 GPU。 */
|
|
24
|
+
interface GeometrySubscriber {
|
|
25
|
+
onGeometryChange(geometry: GeoData): void;
|
|
26
|
+
}
|
|
27
|
+
interface GeoData extends StyleSubscriber {
|
|
28
|
+
readonly id: number;
|
|
29
|
+
readonly type: string;
|
|
30
|
+
readonly version: number;
|
|
31
|
+
style: Style;
|
|
32
|
+
geometry: Float32Array | undefined;
|
|
33
|
+
normal: Float32Array | undefined;
|
|
34
|
+
uv: Float32Array | undefined;
|
|
35
|
+
index: Uint16Array | Uint32Array | undefined;
|
|
36
|
+
linePoints: GeoPartDataLike | undefined;
|
|
37
|
+
vertexType: Float32Array | undefined;
|
|
38
|
+
position: Float32Array | undefined;
|
|
39
|
+
miterScale: Float32Array | undefined;
|
|
40
|
+
readonly uniformData: Float32Array<ArrayBuffer>;
|
|
41
|
+
add(subscriber: GeometrySubscriber): void;
|
|
42
|
+
delete(subscriber: GeometrySubscriber): void;
|
|
43
|
+
updateVersion(): void;
|
|
44
|
+
ensureGeometry(): this;
|
|
45
|
+
updateGeometry(): this;
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
/** CPU 几何及其单一版本;样式订阅只响应影响几何生成的字段。 */
|
|
49
|
+
declare class Geo implements GeoData {
|
|
50
|
+
/** 全局几何 ID。 */
|
|
51
|
+
readonly id: number;
|
|
52
|
+
/** 对象类型。 */
|
|
53
|
+
readonly type: string;
|
|
54
|
+
private _version;
|
|
55
|
+
private _generatedVersion;
|
|
56
|
+
private _style;
|
|
57
|
+
private _disposed;
|
|
58
|
+
private readonly _subscribers;
|
|
59
|
+
/** 合并三角面坐标。 */
|
|
60
|
+
protected _geometry: Float32Array | undefined;
|
|
61
|
+
/** 逐顶点二维轮廓法线。 */
|
|
62
|
+
normal: Float32Array | undefined;
|
|
63
|
+
/** 逐顶点 UV。 */
|
|
64
|
+
uv: Float32Array | undefined;
|
|
65
|
+
/** 合并三角面索引。 */
|
|
66
|
+
index: Uint16Array | Uint32Array | undefined;
|
|
67
|
+
/** 独立 line-list 几何。 */
|
|
68
|
+
linePoints: GeoPartDataLike | undefined;
|
|
69
|
+
/** 顶点用途:0 实体面、0.5 边框、1 关键点。 */
|
|
70
|
+
vertexType: Float32Array | undefined;
|
|
71
|
+
/** 关键点中心,其他顶点填零。 */
|
|
72
|
+
position: Float32Array | undefined;
|
|
73
|
+
/** 边框连接倍率,其他顶点填一。 */
|
|
74
|
+
miterScale: Float32Array | undefined;
|
|
75
|
+
/** 宽高、圆角和实体边框宽度。 */
|
|
76
|
+
readonly uniformData: Float32Array<ArrayBuffer>;
|
|
77
|
+
/** @param style 共享样式,默认四个分区全部关闭 */
|
|
78
|
+
constructor(style?: Style);
|
|
79
|
+
/** 当前共享样式,分区 enabled 决定生成内容。 */
|
|
80
|
+
get style(): Style;
|
|
81
|
+
/** @param value 新样式,先解绑旧样式并使全部几何缓存失效 */
|
|
82
|
+
set style(value: Style);
|
|
83
|
+
/**
|
|
84
|
+
* 只让几何依赖的字段触发重建,颜色和透明度不影响顶点。
|
|
85
|
+
* @param change 样式通知
|
|
86
|
+
*/
|
|
87
|
+
onStyleChange(change: StyleChange): void;
|
|
88
|
+
/** 最终停止使用时解绑 Style;不等于从 Scene 移除,不销毁 Render 缓存。 */
|
|
89
|
+
dispose(): void;
|
|
90
|
+
/**
|
|
91
|
+
* 关联使用当前几何的消费者,重复关联不会重复通知。
|
|
92
|
+
* @param subscriber Mesh 或其他几何消费者
|
|
93
|
+
*/
|
|
94
|
+
add(subscriber: GeometrySubscriber): void;
|
|
95
|
+
/**
|
|
96
|
+
* 解绑消费者,不销毁共享几何或 GPU 缓存。
|
|
97
|
+
* @param subscriber 需要解绑的消费者
|
|
98
|
+
*/
|
|
99
|
+
delete(subscriber: GeometrySubscriber): void;
|
|
100
|
+
/**
|
|
101
|
+
* 获取合并三角面的二维顶点数组。
|
|
102
|
+
* @returns 顶点数组,未生成三角面时为 undefined
|
|
103
|
+
*/
|
|
104
|
+
get geometry(): Float32Array | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* 替换合并三角面顶点数组并通知 GPU 缓存更新。
|
|
107
|
+
* 已生成的 CPU 数据直接提交;尚未生成的参数变化仍由 ensureGeometry 处理。
|
|
108
|
+
* @param geometry 新顶点数组
|
|
109
|
+
*/
|
|
110
|
+
set geometry(geometry: Float32Array | undefined);
|
|
111
|
+
/**
|
|
112
|
+
* 按实体面、宽边框、关键点顺序合并全部三角面并补齐顶点属性。
|
|
113
|
+
* 索引按顶点偏移重新定位,顶点数量超过 Uint16 范围时自动升级位宽。
|
|
114
|
+
* @param parts 本次启用的几何分区
|
|
115
|
+
* @returns 无返回值
|
|
116
|
+
*/
|
|
117
|
+
protected mergeGeometry(parts: {
|
|
118
|
+
data: GeoPartDataLike;
|
|
119
|
+
vertexType: number;
|
|
120
|
+
}[]): void;
|
|
121
|
+
/** 当前几何版本。 */
|
|
122
|
+
get version(): number;
|
|
123
|
+
/** 通知 CPU 生成器及每个 Render 更新缓存。 */
|
|
124
|
+
updateVersion(): void;
|
|
125
|
+
/** 参数变化后延迟生成,一帧内多次改值只生成一次。 */
|
|
126
|
+
ensureGeometry(): this;
|
|
127
|
+
/** 提交生成的数据;手动调用也会递增版本,通知每个 Render。 */
|
|
128
|
+
updateGeometry(): this;
|
|
129
|
+
}
|
|
130
|
+
export default Geo;
|
|
131
|
+
export type { BorderAlign, GeoBuffersLike, GeoData, GeoPartDataLike, GeometrySubscriber };
|