@easytwin/devkit 0.1.0 → 0.1.1

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.
@@ -13,12 +13,17 @@ description: 当用户要开始使用 EasyTwin DevKit、配置应用级凭证(Ap
13
13
  {
14
14
  "appId": "必填",
15
15
  "appSecret": "必填",
16
- "baseUrl": "可选,缺省官方固定域名"
16
+ "env": "可选,prod=正式 / test=测试,缺省 prod",
17
+ "baseUrl": "可选,缺省按 env 选官方域名",
18
+ "ossUrl": "可选,缺省官方 OSS"
17
19
  }
18
20
  ```
19
21
 
20
- - 环境变量 `EASYTWIN_APP_ID` / `EASYTWIN_APP_SECRET` / `EASYTWIN_BASE_URL` 优先于文件(CI 与不落盘场景)。
22
+ - 环境变量 `EASYTWIN_APP_ID` / `EASYTWIN_APP_SECRET` / `EASYTWIN_BASE_URL` / `EASYTWIN_ENV` / `EASYTWIN_OSS_URL` 优先于文件(CI 与不落盘场景)。
23
+ - 官方 API:正式 `http://saas-twin.k8s.dtstack.cn/`、测试 `http://saas-twin-test.k8s.dtstack.cn/`;缺省按 env 选择,`EASYTWIN_BASE_URL` 始终优先。
24
+ - 官方 OSS:`https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/`,供 twin runtime 加载 webp wasm / draco / 组件脚本;`EASYTWIN_OSS_URL` 始终优先。
21
25
  - 该文件含密钥,**永不入库**:`init` 已负责 gitignore,不要把它提交进版本库。
26
+ - **本地测试**:`appId` 与 `appSecret` 都填 `test` 时进入本地测试模式,scene/upload 走本地 mock、不发网络请求(见 easytwin-scene / easytwin-upload)。仅限本地联调,严禁用假凭据碰真实服务端。
22
27
 
23
28
  ## 步骤
24
29
 
@@ -15,7 +15,7 @@
15
15
  ```ts
16
16
  const engine = await RuntimeEngine.create({
17
17
  containerId: "twin-root",
18
- baseOSSUrl: "https://assets.easyv.cloud",
18
+ baseOSSUrl: "https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/",
19
19
  customComponentDeps: { "@easytwin/runtime": Runtime, react: FakeReact },
20
20
  sceneResources: [],
21
21
  componentRels: [],
@@ -25,7 +25,7 @@ const engine = await RuntimeEngine.create({
25
25
  | 字段 | 必填 | 说明 |
26
26
  | --- | --- | --- |
27
27
  | `containerId` | 是 | 容器元素 id;找不到即抛 `cannot find dom with id '<id>'` |
28
- | `baseOSSUrl` | 是 | 服务端资产根地址;draco/ktx2/webp 等系统库 URL 由此拼出 |
28
+ | `baseOSSUrl` | 是 | 官方 OSS 资产根;draco/ktx2/webp custom component script URL 由此拼出 |
29
29
  | `customComponentDeps` | 是 | 自定义组件脚本 import 的依赖表(键=模块名,值=实现) |
30
30
  | `localOSSUrl` | 否 | 本地资产根地址;非空时自定义组件脚本优先读本地 |
31
31
  | `sceneResources` | 否 | 场景资源清单 `ListSceneResourceVo[]`,默认 [] |
@@ -85,4 +85,4 @@ const engine = await RuntimeEngine.create({
85
85
  ## SystemInfo / StatsTool
86
86
 
87
87
  - `SystemInfo`(静态):`platform`(`Platform` 枚举:Android / IPhone / IPad / Mac / Unknown)、`operatingSystem`、`devicePixelRatio`。
88
- - `StatsTool`(场景性能统计):`triangleCount` / `textureRAM` / `textureVRAM` / `lightCount` / `componentCount` / `modelCount` / `materialCount` / `textureMap` / `geometryMap` / `materialMap`,`update()` 重算。
88
+ - `StatsTool`(场景性能统计):`triangleCount` / `textureRAM` / `textureVRAM` / `lightCount` / `componentCount` / `modelCount` / `materialCount` / `textureMap` / `geometryMap` / `materialMap`,`update()` 重算。
@@ -9,7 +9,7 @@ EasyTwin DevKit 是 EasyTwin 第三方应用开发工具集。典型工作流:
9
9
 
10
10
  1. **配置凭证**:运行 `easytwin init` 生成项目级 `easytwin.config.json`(App ID / App Secret)。详见 `easytwin-bootstrap`。
11
11
  2. **拉取场景**:`easytwin scene list` 列出场景,`easytwin scene pull <id>` 拉取场景 JSON 到本地,作为开发参考与预览输入。详见 `easytwin-scene`。
12
- 3. **编写渲染功能**:用 twin runtime(npm `@easytwin/runtime`)开发渲染代码;引擎内核(基类/Time/相机/物理) `easytwin-core`。详见 `easytwin-render`(主力技能)。
12
+ 3. **编写渲染功能**:在工作区 `src/main.ts` 写 `export default async function main(ctx)`(ctx = `{ engine, runtime, sceneJson }`),类型由 `easytwin skills sync` 分发,**不要** `npm install @easytwin/runtime`(公网不存在)。编译用 `easytwin bundle`,运行用插件预览页底部 Run。引擎内核见 `easytwin-core`。详见 `easytwin-render`(主力技能)。
13
13
  4. **上传产物**:`easytwin upload <dir>` 全量覆盖上传到服务端,不可逆。详见 `easytwin-upload`。
14
14
 
15
15
  ## 何时读哪个技能
@@ -22,4 +22,8 @@ EasyTwin DevKit 是 EasyTwin 第三方应用开发工具集。典型工作流:
22
22
  | 理解引擎内核 / 基类 / 相机 / 物理 | easytwin-core |
23
23
  | 上传开发产物 | easytwin-upload |
24
24
 
25
- > 场景 JSON 具体格式尚未定稿,相关说明在 easytwin-scene 中为占位。
25
+ > 场景 JSON 格式以 easytwin-runtime 的 `SceneJson` 为准,详见 easytwin-scene
26
+
27
+ ## 本地测试
28
+
29
+ 没有凭据或不想动服务端时,把 `appId` / `appSecret` 都设为 `test` 即进入本地测试模式:`scene list` / `scene pull` 读 devkit 包内的 `scene.example.json`,`upload` 只做本地空跑,这两条不发服务端请求。插件里的场景预览仍是三维场景页(打包的 twin runtime + 本地示例 JSON),系统库(draco/basis/webp)与组件脚本按官方 OSS(=ossUrl)在线加载。预览页 Run 在 mock 下同样可用。
@@ -1,40 +1,41 @@
1
1
  ---
2
2
  name: easytwin-render
3
- description: 当用户要用 EasyTwin twin runtime 编写渲染功能(安装/引入 @easytwin/runtime、初始化引擎、加载场景、开发自定义组件、调用渲染 API)时使用。这是 EasyTwin 渲染开发的唯一入口技能。
3
+ description: 当用户要用 EasyTwin twin runtime 编写渲染功能( src/main.ts、预览页 Run、easytwin bundle、加载场景、开发自定义组件、调用渲染 API)时使用。这是 EasyTwin 渲染开发的唯一入口技能。
4
4
  ---
5
5
 
6
6
  # 用 twin runtime 开发渲染功能
7
7
 
8
- twin runtime npm `@easytwin/runtime`(ESM,peer 依赖 `three@0.183.0`):在已存在的 DOM 容器上创建 `RuntimeEngine`,加载场景 JSON,通过组件生命周期与渲染 API 开发功能。
8
+ `@easytwin/runtime` 是商业包,公网 npm 不存在,**严禁** `npm install @easytwin/runtime`。类型声明由 `easytwin skills sync` 写入项目 `.easytwin/types/`;运行走预览页底部 **Run** 按钮,或 `easytwin bundle` 做编译校验。
9
9
 
10
- ## 快速上手
10
+ ## 编写与运行 main.ts
11
11
 
12
- 1. 安装:`npm i @easytwin/runtime`(项目需自装 peer 依赖 `three@0.183.0`)
13
- 2. 页面里先放好容器 `<div id="twin-root"></div>` ——容器必须已存在于 DOM,`RuntimeEngine.create` 找不到会抛错。
14
- 3. 初始化并加载场景:
12
+ 工作区固定入口 `src/main.ts`(缺失则编译报错)。只能依赖 `@easytwin/runtime`(相对路径的本地 TS 可以),禁止任何其他裸模块。
15
13
 
16
14
  ```ts
17
- import { RuntimeEngine, SceneManager, LoadSceneMode } from "@easytwin/runtime";
18
-
19
- const engine = await RuntimeEngine.create({
20
- containerId: "twin-root",
21
- baseOSSUrl: "https://assets.easyv.cloud",
22
- customComponentDeps: { "@easytwin/runtime": Runtime, react: FakeReact },
23
- sceneResources: [],
24
- componentRels: [],
25
- });
26
- await engine.getManager(SceneManager).loadScene(sceneJson, "publish", LoadSceneMode.Single);
15
+ import type { EasyTwinRunContext } from "@easytwin/runtime";
16
+
17
+ export default async function main(ctx: EasyTwinRunContext) {
18
+ const { engine, runtime, sceneJson } = ctx;
19
+ // 在已加载的场景上写渲染/交互逻辑
20
+ void engine;
21
+ void runtime;
22
+ void sceneJson;
23
+ }
27
24
  ```
28
25
 
29
- 4. 在组件生命周期/事件里写渲染逻辑;自定义组件继承 `Component` / `VirtualRootComponent`,见 `references/lifecycle-events.md`。
26
+ 1. 若还没有类型:运行 `easytwin skills sync`(无 tsconfig 会生成最小配置;已有 tsconfig 时在输出里看 `paths` 片段,自行加上 `"@easytwin/runtime": [".easytwin/types"]` 并建议 `skipLibCheck: true`)。
27
+ 2. 编译校验:`easytwin bundle`(缺省写出 `dist/main.js`,ESM + inline sourcemap)。检测到 lodash 等外部依赖会给出人话报错,不要据此去 npm install。
28
+ 3. 运行:打开插件场景预览,点底部 **Run**。宿主内存编译(不落盘)→ blob URL + import map 把 `@easytwin/runtime` 指到页面已加载的同一 runtime 实例 → 先重新 `loadScene` 再调用 `export default main(ctx)`。编译失败不打断已渲染场景;mock 下同样可用。
30
29
 
31
- > TODO(外部输入): 官方"script 引入全局对象"的加载方式尚未确认。当前以 npm 包 `@easytwin/runtime` + `RuntimeEngine.create` 为准;若官方后续给出 script 方式,在此补充并同步更新 references。
30
+ `ctx`:`engine` 是现成 `RuntimeEngine`;`runtime` 是整个模块命名空间(枚举/类从此取);`sceneJson` 是当前场景数据。
31
+
32
+ 完整「自己 create engine」的 API 细节见下方 references;预览页 Run 走注入式 ctx,不必在 main.ts 里再 `RuntimeEngine.create`。
32
33
 
33
34
  ## 参考(references/)
34
35
 
35
36
  API 细节按域拆分,按需加载,不要一次全读:
36
37
 
37
- - 需要"安装、初始化引擎、engine/scene/manager 关系、销毁"时读 `references/intro.md`
38
+ - 需要"初始化引擎、engine/scene/manager 关系、销毁"时读 `references/intro.md`
38
39
  - 需要"场景加载/序列化结构/资产加载"时读 `references/scene-and-assets.md`
39
40
  - 需要"组件生命周期、状态/数据、事件"时读 `references/lifecycle-events.md`
40
41
  - 需要"相机/坐标、2D、动画、物理、地理、工具函数"时读 `references/rendering-apis.md`
@@ -2,9 +2,8 @@
2
2
 
3
3
  ## 包信息
4
4
 
5
- - npm 包:`@easytwin/runtime`(ESM 模块)。
6
- - peer 依赖:`three@0.183.0`(需自行安装);内部依赖 rapier3d、@tweenjs/tween.js、mobx、localforage、proj4、stats-gl 等,由包自身携带。
7
- - 根导出:`manager`、`core`、`loader`、`utils`、`packages`、`server`、`type`、`three-extension`、`constants`、`module` 命名空间;另有 `THREE`、`Mobx`、`TweenJs`、`Semver` 命名空间与若干直接导出(详见 rendering-apis.md)。
5
+ - npm 包名:`@easytwin/runtime`(商业包,公网不存在)。**不要** `npm install`;类型由 `easytwin skills sync` 写入 `.easytwin/types/`,运行走预览页 Run 或 `easytwin bundle`。
6
+ - 用户代码入口:`src/main.ts` 的 `export default async function main(ctx)`,ctx 由预览页注入,一般不必自己 `RuntimeEngine.create`。
8
7
 
9
8
  ## 初始化 RuntimeEngine
10
9
 
@@ -15,7 +14,7 @@ import { RuntimeEngine, SceneManager, LoadSceneMode } from "@easytwin/runtime";
15
14
 
16
15
  const engine = await RuntimeEngine.create({
17
16
  containerId: "twin-root", // 必填:容器 id,须已存在于 DOM
18
- baseOSSUrl: "https://assets.easyv.cloud", // 必填:资产根地址
17
+ baseOSSUrl: "https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/", // 必填:官方 OSS 资产根
19
18
  customComponentDeps: { /* 见下 */ }, // 必填:注入给自定义组件的依赖
20
19
  sceneResources: [], // 可选:场景资源清单,默认 []
21
20
  componentRels: [], // 可选:组件引用关系,默认 []
@@ -29,7 +28,7 @@ const engine = await RuntimeEngine.create({
29
28
  | 字段 | 必填 | 说明 |
30
29
  | --- | --- | --- |
31
30
  | `containerId` | 是 | 容器元素 id;`document.getElementById(containerId)` 找不到即抛错 |
32
- | `baseOSSUrl` | 是 | 服务端资产根地址;draco / ktx2 / webp / LCC 等系统库 URL 由此拼出 |
31
+ | `baseOSSUrl` | 是 | 官方 OSS 资产根;draco / ktx2 / webp / 组件脚本 URL 由此拼出(`{baseOSSUrl}/easytwin/system/libs/…`、`{baseOSSUrl}/easytwin/system/components/custom/…`) |
33
32
  | `customComponentDeps` | 是 | 自定义组件脚本 import 的依赖表,键为模块名,值为实现 |
34
33
  | `localOSSUrl` | 否 | 本地资产根地址;非空时自定义组件脚本优先读 `${localOSSUrl}/${type}@${version}.js` |
35
34
  | `sceneResources` | 否 | 场景资源清单(ListSceneResourceVo[]) |
@@ -78,4 +77,4 @@ RuntimeSceneMode = { Editor: "editor", Preview: "preview", EasyV: "easyV", Publi
78
77
 
79
78
  ## 参考源码
80
79
 
81
- - `src/core/RuntimeEngine.ts`、`src/core/RuntimeScene.ts`、`src/core/Time.ts`。
80
+ - `src/core/RuntimeEngine.ts`、`src/core/RuntimeScene.ts`、`src/core/Time.ts`。
@@ -1,6 +1,6 @@
1
1
  # 场景加载与资产
2
2
 
3
- > 说明:本节讲的是 **runtime 内部**的场景 JSON(组件树序列化结构,`SceneJson`)与资产加载;`easytwin scene pull` 拉的是**服务端场景 JSON**,两者出处不同。可用 `SceneManager.importScene` 或 `loadScene` 把本地 JSON 喂给 runtime。
3
+ > 说明:本节讲的是 runtime 的场景 JSON(组件树序列化结构,`SceneJson`,定义见 `src/core/interface.ts`)与资产加载。`easytwin scene pull` 拉取的服务端场景 JSON 同样以该结构为准(见 easytwin-scene)。可用 `SceneManager.importScene` 或 `loadScene` 把本地 JSON 喂给 runtime。
4
4
 
5
5
  ## 场景管理(SceneManager)
6
6
 
@@ -74,7 +74,8 @@ interface SceneJson { id: string; name: string; sceneComponent: ComponentJson; }
74
74
  - `loadModelAsync(address, onProgress?)` → `GLTFLoadResult`(带缓存;失败 fallback 默认模型)。
75
75
  - `getModelInitData(url, onProgress?)` → `{ animation, sceneGraph, materialSlots, materialMap }`;animation 项:`autoPlay / loop("repeat"|"once"|"pingpong") / stopAtEnd / timeScale / id / name`。
76
76
  - `loadTextureAsync(address, onProgress?)`;`loadVideoTextureAsync(address)`(自动建 video:`muted`、`loop`、`playsInline`、`crossOrigin: "anonymous"`,mp4 source);`loadHDRTextureAsync(address, onProgress?)`(`.exr` 走 EXRLoader,否则 RGBELoader,自动 `EquirectangularReflectionMapping`)。
77
- - `loadCustomComponentScript(type, version, externalDeps)`:localOSSUrl 非空优先读 `${localOSSUrl}/${type}@${version}.js`,否则 `${baseOSSUrl}/easytwin/system/components/custom/${type}/${version}/script.js`。
77
+ - `loadCustomComponentScript(type, version, externalDeps)`:localOSSUrl 非空优先读 `${localOSSUrl}/${type}@${version}.js`,否则 `${baseOSSUrl}/easytwin/system/components/custom/${type}/${version}/script.js`(例:`https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/easytwin/system/components/custom/Postprocessing/0.0.9/script.js`)。
78
+ - 系统库同样由 `baseOSSUrl` 拼出:webp wasm 为 `${baseOSSUrl}/easytwin/system/libs/webp-wasm.wasm`,draco 为 `${baseOSSUrl}/easytwin/system/libs/draco/`。
78
79
  - `cacheModelByFileAsync(file, address)`;`instantiateModel(model)`(同 url 共享 geometry/纹理源);`getResourceUrl(relativeUrl)`。
79
80
 
80
81
  **资源路径约定(README)**:data 和 state 中**以 `$R` 结尾的字段**会被判定为资源路径,要求 value 是 string,参与导入导出(如 `url$R`)。
@@ -91,4 +92,4 @@ options = {
91
92
  ```
92
93
 
93
94
  - 默认 `useEnv` / `useIndexDB` / `useLoadingEffect` 为 `true`,`enableCollision` 为 `false`;返回实例 id,失败 `null`。
94
- - `scene.unloadLCC(id)` / `scene.unloadAllLCC()`;`scene.clearLCC()` 只清实例,保留 `window.LCCRender` 便于复用。
95
+ - `scene.unloadLCC(id)` / `scene.unloadAllLCC()`;`scene.clearLCC()` 只清实例,保留 `window.LCCRender` 便于复用。
@@ -10,10 +10,38 @@ description: 当用户要列出场景、查看有哪些场景、或把某个场
10
10
 
11
11
  ## 场景 JSON 格式
12
12
 
13
- <!-- TODO(外部输入): 场景 JSON 具体格式尚未定稿。格式到位后在此补充字段说明,并同步更新 scene/upload 实现与场景预览。 -->
14
- 场景 JSON 的字段结构待定(向 EasyTwin 维护者索取)。当前拉取结果按服务端原样保存,字段以实际返回为准。
13
+ 场景 JSON easytwin-runtime `SceneJson` 为准(`packages/easytwin-runtime/src/core/interface.ts`),即组件树序列化结构:
15
14
 
16
- > 注意:此处是**服务端场景 JSON**;runtime 内部用于 loadScene 的 SceneJson(组件树序列化结构)见 easytwin-render 的 references/scene-and-assets.md,两者出处不同。
15
+ ```ts
16
+ type StateJson<T = any> = { id: string; name: string; config: T; using: boolean; rank: number };
17
+
18
+ type ComponentJson<S = any, D = any> = {
19
+ id: string; // 实体 id,仅用于层级关系
20
+ active: boolean; // 世界大纲 config 修改
21
+ lock: boolean; // 仅编辑器生效(是否被选中)
22
+ collapsed: boolean; // 世界大纲 config 修改
23
+ componentId: string; // 组件 id,兼容后端绑定关系
24
+ name: string;
25
+ type: string;
26
+ version: string;
27
+ states?: StateJson<S>[];
28
+ data?: D;
29
+ children: ComponentJson[];
30
+ parentId: string | null; // 引擎不直接存储 parentId
31
+ };
32
+
33
+ interface SceneJson { id: string; name: string; sceneComponent: ComponentJson; }
34
+ ```
35
+
36
+ `easytwin scene pull` 按服务端原样保存;该结构可直接作为渲染开发参考与本地预览输入(runtime 的 `SceneManager.loadScene` / `importScene` 接受它,详见 easytwin-render 的 references/scene-and-assets.md)。
37
+
38
+ ## 本地测试模式(mock)
39
+
40
+ 当 `appId` 与 `appSecret` 均为 `test` 时,`scene list` / `scene pull` 不再请求服务端,改读 devkit 包内 `scene.example.json`:
41
+
42
+ - 场景 id 取 `objs[].sceneId` 首个非空值(当前示例为 `sceJTHH9yoqFyRyS9`),场景名固定为「本地示例场景」;
43
+ - `scene pull` 的 id 必须与示例 id 一致,否则报错;
44
+ - 命令输出会标注「本地测试模式」。该模式仅用于本地联调,不发网络请求。
17
45
 
18
46
  ## 典型用法
19
47
 
@@ -22,5 +50,5 @@ description: 当用户要列出场景、查看有哪些场景、或把某个场
22
50
  ```bash
23
51
  easytwin scene list
24
52
  easytwin scene pull scene-123 --out ./scenes/scene-123.json
25
- ```
26
-
53
+ ```
54
+
@@ -15,6 +15,10 @@ description: 当用户要把本地开发产物目录上传回 EasyTwin、全量
15
15
  - 逐文件 multipart 上传,带进度输出。
16
16
  - 上传目标空间由凭据(App ID)决定;pull 场景与 upload 目录是两条独立能力,互不引用。
17
17
 
18
+ ## 本地测试模式(mock)
19
+
20
+ 当 `appId` 与 `appSecret` 均为 `test` 时,`easytwin upload <dir>` 退化为本地空跑(dry-run):只收集与统计文件、不上传,进度照常上报,输出标注「本地测试模式」。适合在无凭据/不想动服务端时演练上传流程。
21
+
18
22
  ## 步骤
19
23
 
20
24
  1. 确认目标空间(App ID)与目录内容。